web-dev-qa-db-ja.com

GNU grepの-oオプションは長さがゼロの一致を無視しますか?

別のサイトでgrep -oP '^\w+|$を示唆する回答が見つかりました。 |$はPCREでは無意味であることを指摘しました。これは「OR行末」を意味するだけなので、通常の行では常にtrueになるためです。ただし、GNU grep PCREsを-oと組み合わせた場合、それが何をするのかを正確に理解することはできません。以下を考慮してください。

$ printf 'ab\na\nc\n\n' | Perl -ne 'print if /ab|$/'
ab
a
c

$

(空の行が結果に含まれていることを示すために、2番目のプロンプト($)文字を含めています)。

予想通り、Perlでは、すべての行に一致します。 abが含まれているため、または$が行末と一致しているためです。 GNU grep-oフラグなしでも同じように動作します:

$ printf 'ab\na\nc\n\n' | grep -P 'ab|$'
ab
a
c

$

ただし、-oは動作を変更します。

$ printf 'ab\na\nc\n\n' | grep -oP 'ab|$'
ab
$

これは、abを単にgreppingするのと同じです。 2番目の部分である「OR行末」は無視されているようです。 -oフラグがなくても期待どおりに機能します。

どうしたの? -oは長さ0の一致を無視しますか?それはバグですか、それとも予想されますか?

8
terdon

私のGNU grep manページは次のように述べています:

-o、-only-matching

一致する行の一致した(空でない)部分のみを出力し、そのような部分はそれぞれ別の出力行に出力します。

強調は私のものです

行末の一致は「空の一致」と見なされていると思います

10
jesse_b

ORの側面

2番目の部分である「OR行末」は無視されているようです。

いいえ、一致を少し変更すると、そうではありません。

$ printf 'ab\na\n\nc\n' | grep -oP 'ab|.$'
ab
a
c

[〜#〜]または[〜#〜]の両方の部分が明示的に一致しています。

空のマッチ

is無視されるのは「空の」一致です(結果の文字列の長さはゼロです):

$ printf '%s\n' ab " " a "" c | grep -oP '^.*$'
ab

a
c

文書化されています(GNU grep)LESS=+'/^ *-o,' man grep(鉱山を強調):

-o、-only-matching
Print only the matched (空ではない) parts of a matching line, with each such part on a separate output line.

0
Isaac