web-dev-qa-db-ja.com

正規表現がgrepで機能しない

私はこの正規表現を持っています:

(?<=prefix).*$

これは、文字列 "prefix"に続く任意の文字を返し、オンラインの正規表現エンジンで正常に機能します(例 https://regex101.com )。問題は、その正規表現をbashで使用する場合です。

grep '(?<=prefix).*$' <<< prefixSTRING

何にも一致しません。なぜその正規表現がgrepで機能しないのですか?

13
mark009

正しい正規表現を定義したようですが、grepが理解できるようにコマンドラインで十分なフラグを設定していません。デフォルトでは、grepはBREをサポートし、-Eフラグを指定するとEREを実行するためです。あなたが持っているもの(先読み)は、-Pフラグを指定したGNU grepでのみサポートされているPCRE正規表現フレーバーでのみ使用できます。

prefixの後に一致する文字列を抽出するのみする必要があると仮定すると、追加のフラグ-oを追加して通知する必要がありますgrep that that printonlymatching part as as

grep -oP '(?<=prefix).*$' <<< prefixSTRING

デフォルトでPCREライブラリをサポートするgrepのバージョンもあります- pcregrep だけで実行できます

pcregrep -o '(?<=prefix).*$' <<< prefixSTRING

さまざまな正規表現のフレーバーに関する詳細な説明は、この素晴らしい Gilesの答え と、それぞれを実装するツールで説明されています

38
Inian

正規表現にはさまざまなフレーバーがあります。表示しているのは、Perlに似た正規表現(PCRE、「Perl互換の正規表現」)です。

grepはPOSIX正規表現を行います。これらは 基本正規表現 (BRE)および 拡張正規表現-Eオプションでgrepが使用されている場合はERE)です。 re_formatまたはregexのマニュアル、またはgrepマニュアルがシステムで参照している同様のマニュアル、または先ほどリンクしたPOSIX標準テキストを参照してください。

GNU grepを使用する場合、GNU grep- specific -Pオプションを指定してgrepを使用すると、Perlのような正規表現を使用できます。

また、grepは、デフォルトではlinesを返しますが、行の部分文字列ではありません。繰り返しますが、GNU grep(およびその他のgrepの実装)では、-oオプションを使用して、各行から指定された式に一致するビットのみを取得できます。

-P-oはどちらも非標準の拡張機能であることに注意してください POSIX仕様のgrep

GNU grepを使用していない場合は、代わりにsedを使用して、文字列prefixと行の終わりの間のビットを取得できます。

sed -n 's/.*prefix\(.*\)/\1/p' file

これは、sedが指定された置換を適用するために管理する行のみを出力することです。置換は、式(BRE)に一致する行全体を、文字列prefixの後に出現する部分で置き換えます。

行にprefixのインスタンスが複数ある場合、sedバリエーションはlastの後に文字列を返し、GNU grepバリエーションは文字列を返します。 firstの後の文字列(prefixの他のインスタンスが含まれます)。

sedソリューションは、すべてのUnixライクなシステムに移植可能です。

38
Kusalananda

他の回答が述べているように、grepは後読みで正規表現フレーバーを使用しません(デフォルトではGNU grep、または他のバージョンではまったく使用しません)。 。

GNU grepまたはpcregrepを使用できない場合は、Perlがあれば使用できます。

Perlと同等のコマンドラインは次のようになります。

Perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING

スラッシュの間に目的の正規表現を入れます。 Perlを使用しているので、これは Perlの正規表現フレーバー を使用します。

6
quantum