web-dev-qa-db-ja.com

複数行を除くpcregrep正規表現は必要以上に1行多く消費します

bananaで始まるすべての行と、バナナの行の後のスペースで始まるすべての行を除外したいと思います。 pcregrepを使用しています。次のファイルを検討してくださいfruits.txt

Apple
banana starts matching
 this line should match
 this too
 and this
mango
pomelo

pcregrepは私が欲しいものを喜んで見つけます:

ars@ars-thinkpad ~/tmp/tmp $ pcregrep -M  'banana.*\n(\s.*\n)*' fruits.txt 
banana starts matching
 this line should match
 this too
 and this

ただし、これらの行を除外しようとすると、pcregrepもマンゴーを食べます。これは良くありません。

ars@ars-thinkpad ~/tmp/tmp $ pcregrep -M -v 'banana.*\n(\s.*\n)*' fruits.txt 
Apple
pomelo

どうして?

1
ars

正規表現で_\s_を使用すると、式が改行を食べることができます。 _-v_がpcregrepにどのように実装されているかを十分に理解していないため、逆ではない理由を理解できませんが、それが原因であると確信しています。

ファイルを次のように変更した場合:

_Apple
banana starts matching
 this line should match
 this too
 and this

mango

pomelo
_

次に、_-v_がなくても、マッチングは意図したものではないように見えます。

_$ pcregrep  -M 'banana.*\n(\s.*\n)*' fruits.txt
banana starts matching
 this line should match
 this too
 and this

mango

pomelo
_

一致する必要があるのが本当に行の先頭のスペースだけである場合は、_\s_を1つ以上のスペース_" +"_に変更することをお勧めします。

正規表現を'banana.*\n( +.*\n)*'に変更すると、より正確だと思う方法で(正規表現と逆関数の両方で)一致します。タブも許可されている場合は、_[ \t]+_を使用することもできます。

1
BowlOfRed

このようなタスクは、awkimoに適しています

$ awk '!/^ /{f=0} /^banana/{f=1} f' fruits.txt 
banana starts matching
 this line should match
 this too
 and this
$ awk '!/^ /{f=0} /^banana/{f=1} !f' fruits.txt 
Apple
mango
pomelo
  • フラグの設定順序は、bananaで始まる行についても!/^ /条件が満たされるため、検索対象の特定の行を簡単に印刷または無効にするのに役立ちます。
  • !/^ /{f=0}行がスペースで始まらない場合は、フラグをクリアします
  • /^banana/{f=1}行がbananaで始まる場合にフラグを設定します
  • fは条件に一致する行を出力し、!fは条件を否定します
0
Sundeep