grepは指定されたグループに一致する出力のみを出力できますか?

grepは指定されたグループに一致する出力のみを出力できますか?

ファイルがあるとしましょう。

# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar

「foobar」の後にどの単語が続くかを知りたいので、次の正規表現を使用できます。

"foobar \(\w\+\)"

括弧は、私がfoobarの後の単語に特に興味があることを示します。しかし、これを行うと、grep "foobar \(\w\+\)" test.txt「foobarの後の単語」だけでなく、正規表現全体に一致する行全体が得られます。

foobar bash 1
foobar happy

私はコマンドの出力が次のようになりたいと思います。

bash
happy

正規表現のグループ化(または特定のグループ化)に一致する項目のみを出力するようにgrepに指示する方法はありますか?

答え1

GNU grepには、-PPerlスタイルの正規表現オプションとパターンに-o一致するもののみを印刷するオプションがあります。これはLookaroundアサーションを使用して組み合わせることができます(以下の説明を参照)。Perlre マンページの拡張モード)は、ターゲットと一致すると判断されたものからgrepパターンの一部を削除します-o

$ grep -oP 'foobar \K\w+' test.txt
bash
happy
$

これは、出力したいテキストの前に幅0のLookBehindアサーションとして使用できる\K短い形式(より効率的です)です。出力するテキストの後に幅0の予測アサーションとして使用できます。(?<=pattern)(?=pattern)

fooたとえば、との間の単語を一致させるには、bar次のようにします。

$ grep -oP 'foo \K\w+(?= bar)' test.txt

または(対称のため)

$ grep -oP '(?<=foo )\w+(?= bar)' test.txt

答え2

    sed -n "s/^.*foobar\s*\(\S*\).*$/\1/p"

-n     suppress printing
s      substitute
^.*    anything before foobar
foobar initial search match
\s*    any white space character (space)
\(     start capture group
\S*    capture any non-white space character (word)
\)     end capture group
.*$    anything after the capture group
\1     substitute everything with the 1st capture group
p      print it

答え3

標準のgrepはこれを行うことはできませんが、最新バージョンのGNU grepでは、次のことができます。。 sed、awk、perl を使用できます。以下は、サンプル入力で必要な操作を実行するいくつかの例です。特別な場合は少し異なる動作をします。

foobar word other stuffに交換wordし、交換が完了した後にのみ印刷します。

sed -n -e 's/^foobar \([[:alnum:]]\+\).*/\1/p'

最初の単語がある場合は、foobar2番目の単語を印刷します。

awk '$1 == "foobar" {print $2}'

foobar最初の単語の場合は削除し、そうでない場合は行をスキップし、最初のスペースの後のすべての項目を削除して印刷します。

perl -lne 's/^foobar\s+// or next; s/\s.*//; print'

答え4

もちろん、foobarが常に最初の単語または行であることを知っている場合は、cutを使用できます。このように:

grep "foobar" test.file | cut -d" " -f2

関連情報