PCRE-regex は grep を使用してキャプチャグループを除外します。

PCRE-regex は grep を使用してキャプチャグループを除外します。

ファイルの文字列を一致させるためにGNU grepPCRE正規表現サポートを使用しています。-P入力ファイルには、次の文字列を含む行が含まれています。

FOO_1BAR.zoo.2.someString:More-RandomString (string here too): 0.45654343

上記の行の数字2と数字をキャプチャしたいと思います。0.45654343正規表現を使用しました。

grep -Po ".zoo.\K[\d+](.*):\ (.*)$" file

しかし、私にとって結果は

2.someString:More-RandomString (string here too): 0.45654343

最初のキャプチャグループから最初の数字を取得でき2、行末のキャプチャグループとも一致させることができます。ただし、2つのキャプチャグループ間の単語/行をスキップすることはできません。

私は(.*)これらの単語を真ん中に捉えているグループがあることを知っています。私がやろうとしているのは、\Kそれを無視するために他のものを含めることです。

grep -Po ".zoo.\K[\d+](.*):\K (.*)$" file

しかし、これは私に2番目のキャプチャグループを0.556984

(?:)構文が次のような非キャプチャグループもあります。

grep -Po ".zoo.\K[\d+](?=.someString:More-RandomString (string here too)):\ (.*)$"

しかし、それは私に何も持ってこなかった。私がここで何を見逃しているのでしょうか?

ベストアンサー1

grep名前はg/re/p edコマンドの後に表示されます。主な目的は、正規表現に一致する行を印刷することです。これはこの行の内容を編集することではありません。あなたはsed(ストリームエディタ)またはawkこれのためにいます。

GNU以降grep、一部の実装では、各行の一致部分(キャプチャグループの一致部分ではなく正規表現が一致する部分)を印刷するオプションをgrep追加します。-oすでにgrepGNUに似た実装(使用-P)またはpcregrepPCREの正規表現サポートがあります。

pcregrep実際に-o<n>キャプチャグループの内容を印刷するオプションが追加されました。だからあなたはこれを行うことができます:

pcregrep -o1 -o2 --om-separator=' ' '.zoo.(\d+).*:\s+(.*)'

ただし、ここで明確な標準的な解決策は次のものを使用することですsed

sed -n 's/^.*\.zoo\.\([0-9]\{1,\}\).*:[[:space:]]\{1,\}/\1 /p'

または、perl正規表現が必要な場合は、perlを使用してください。

perl -lne 'print "$1 $2" if /\.zoo\.(\d+).*:\s+(.*)/'

GNUを使用してgrep一致が別の行に表示されるのが気に入らない場合は、次のようにします。

$ grep -Po '\.zoo\.\K\d+|:\s+\K.*' < file
2
0.45654343

一致する区間の先頭がリセットされても、交互\Kに重なる2つの区間を削除できるわけではありません。

grep -Po '.zoo.(\K\d+|.:\ケイ。

動作しません。動作しません(およびecho foobar | grep -Po 'foo|foob'両方印刷)。最初に一致し、次に入力で他の潜在的な一致を探します。したがって、ofで始まるので、それ以降は一致するものが見つかりません。foofoobfoo|foobfoogrepfoobbar

上記では、grep -Po '\.zoo\.\K\d+|:\s+\K.*'シフトの2番目の部分だけを見ました。:<spaces><anything>これは次の部分と一致しますが、それに続く部分だけでなく、入力のどこでもその部分を見つけるという.zoo.<digits>意味でもあります。:<spaces><anything>.zoo.<digits>

ただし、この問題を解決するには、別のPCRE特殊演算子を使用することです\G\Gトピックの先頭に一致します。単一の一致の場合は同じですが、複数の^一致の場合(sed/perlフラグを考えてみてください)、行ですべての一致を検索しようとするのと同じで、前の一致が終了した後も一致します。その場合は、次のようにしてください。gs/.../.../g-ogrep

grep -Po '\.zoo\.\K\d+|(?!^)\G.*:\s+\K.*'

(?!^)否定予測演算子はどこにありますか?行の先頭にない\G最後に成功した(空ではない)一致の後にのみ一致するため、最後に成功した一致.*:\s+\K.*以降にのみ一致し、.foo.<digits>置換の別の部分が行の最後まで一致するため、この一致のみが一致します。

次のように入力すると:

.zoo.1.zoo.2 tar: blah

これにより、以下が出力されます。

1
2
blah

しかし。これを望まない場合は、シフトの最初の部分が行の先頭でのみ一致するようにすることもできます。それはまるで

grep -Po '^.*?\.zoo\.\K\d+|(?!^)\G.*:\s+\K.*'

またはのような入力では依然として出力されます2。置換の最初の部分でプレビュー演算子を使用し、その後にスペース以外の1つ以上を見つけてこの問題を解決できます(文字以外の問題を回避するためにも使用できます)。.zoo.2 no colon character.zoo.2 blah::<spaces>$

grep -Po '^.*?\.zoo\.\K\d+(?=.*:\s+\S.*$)|(?!^)\G.*:\s+\K\S.*$'

sedその正規表現を説明するには複数ページのコメントが必要になる可能性があるため、まだ直接/ソリューションを使用しますperl

おすすめ記事