ファイル内の複数行パターンを検索するにはどうすればよいですか?


128

特定の文字列パターンを含むすべてのファイルを見つける必要がありました。心に来る最初のソリューションを使用している検索をしてパイプxargsのはgrep

find . -iname '*.py' | xargs grep -e 'YOUR_PATTERN'

しかし、複数の行にまたがるパターンを見つける必要がある場合、バニラgrepは複数行のパターンを見つけることができないため、行き詰まります。



2
これは古いので、重複していないと思います:)
rogerdpack

@rogerdpack質問を重複としてマークする場合、回答の量と質、および質問の質の後に、質問の年齢が第3の懸念事項です。
Tripleee

回答:


98

そこで、Perl互換正規表現GREPを表すpcregrepを発見しました。

たとえば、 ' _name '変数の直後に ' _description '変数が続くファイルを見つける必要があります。

find . -iname '*.py' | xargs pcregrep -M '_name.*\n.*_description'

ヒント:パターンに改行文字を含める必要があります。プラットフォームによっては、 '\ n'、\ r '、' \ r \ n '、...


7
以下のhalkaで述べたように、「正規表現に(?s)を追加すると、ドットワイルドカードを使用して改行を一致させることもできます」。次に、-Pを追加して、perl regexでgrepを使用します。見つける。-exec grep -nHP '(?s)SELECT。{1,60} FROM。{1,20} table_name' '{}' \;
ジム

8
pcregrepMacで利用可能brew install pcre
Jared Beck

1
さらに良い:-H各一致の前にファイル名を出力する使用:pcregrep -HM
Ciro Santilli郝海东冠状病六四事件法轮功

97

なぜあなたが行かないのawk

awk '/Start pattern/,/End pattern/' filename

2
これは理解しやすくawk、ほとんどの* nixシステムに付属する使用法です。
Ali Karbassi、2011年

24
いいね!このマッチを貪欲でないようにする方法はありますか?
marcin

3
一致する場合のみ、ファイル名をどのように印刷しますか?
bibstha 2012

2
でマッチの行番号を表示できawk '/Start pattern/,/End pattern/ {printf NR " "; print}' filenameます。行番号に固定幅を指定することにより、見栄えを良くすることができますawk '/Start pattern/,/End pattern/ {printf "%-4s ", NR; print}' filename
Robert

これは単一のファイルでうまく機能するようですが、複数のファイル内を検索したい場合はどうなりますか?
ジンストロング、

84

GNUgrepを使用した例を次に示します

grep -Pzo '_name.*\n.*_description'

-z/ --null-data入力および出力データを一連の線として扱います。

こちらもご覧ください


1
それは単一の改行文字を説明するだけだと思います。
Cloud

1
フラグを使用-zしないと複数行の検索にgrepを使用できなかったため、検索が1行で分割され-oず、一致した部分のみが印刷されました。
bbaja42 2012年

-oによって何も印刷されないことがわかりましたが、-lはファイルのリストを取得するために機能しました(私のコマンドはgrep -rzl pattern *、-rzoは機能しませんでした)
Benubird

5
非ASCIIファイルの場合は、「- Pzo」ではなく「grep -Pazo」をお勧めします。非ASCIIファイルの-zスイッチは、戻り値を変更するgrepの「バイナリデータ」動作をトリガーする可能性があるため、より良い方法です。スイッチ '' -a | --text」はそれを防ぎます。
rloth、2015年

gitがインストールされているMacでは動作しませんbrew reinstall --with-pcre git
Quanlong

21

grep -Pまたlibpcreを使用しているが、ずっとより広くインストールされています。titleHTMLドキュメントの完全なセクションを見つけるには、たとえそれが複数行にわたる場合でも、これを使用できます。

grep -P '(?s)<title>.*</title>' example.html

以来PCREプロジェクト perlの標準を実装し、参考のためにperlのドキュメントを使用します。


うーん、今すぐ試してみましたが、動作していないようです... gist.github.com/rdp/0286d91624930bd11d0169d6a6337c33
rogerdpack

grepにこのオプションがあることを知りませんでした。おそらくこのため:これは非常に実験的なものであり、grep -Pは実装されていない機能について警告する場合があります。; これは CentOS 7の下にあります。Fedora29の下:これは実験的なものであり、grep -Pは実装されていない機能を警告する場合があります。もちろん、BSD grepにはまったくありません。それほど実験的ではなかったとしても良かったのですが、思い出させていただければ嬉しいです。
Pryftan

17

以下に、より便利な例を示します。

pcregrep -Mi "<title>(.*\n){0,5}</title>" afile.html

5行までの場合でも、htmlファイルのタイトルタグを検索します。

以下は無制限の行の例です。

pcregrep -Mi "(?s)<title>.*</title>" example.html 

4
これをありがとう。ワイルドカードが改行文字と一致しないことに気付かなかった。
マット

7
@matt:あなたはまた、あなたが追加した場合改行に一致するようにドットワイルドカードを説得することができ(?s)、あなたの正規表現にそうように、:"(?s)<html>.*</html>"
lubomir.brindza

@mattもちろん、$(パターンの終わりで)チェックして、それが行の終わりであることを示すことができます。もご覧くださいglob(7)。また、この興味深いWebサイトを見つけることもできます:regular-expressions.info
Pryftan


4

ここでgrep代替シフトを使用できます(免責事項:私が作成者です)。

複数行のマッチングをサポートし、すぐに使用できる特定のファイルタイプに検索を制限します。

sift -m --files '* .py' 'YOUR_PATTERN'

(指定された複数行の正規表現パターンのすべての* .pyファイルを検索します)

すべての主要なオペレーティングシステムで使用できます。見てみましょうサンプル・ページにはXMLファイルから複数行の値を抽出するために使用する方法を参照してください。


3

この答えは役に立つかもしれません:

複数行の検索に必要な正規表現(grep)

再帰的に検索するには、フラグ-R(再帰的)および--include(GLOBパターン)を使用できます。見る:

特定のファイルをgrepしないようにするには、grep --exclude /-include構文を使用します


@ƉiamondǤeezeƦLQP(stackoverflow.com/review/low-quality-posts/19341146)で投稿を編集するとレビューが無効になるので、投稿を維持する必要があることが確かな場合は編集してください。
fedorqui 'SO stop harming'

2

@Marcin:欲張らないawkの例:

awk '{if ($0 ~ /Start pattern/) {triggered=1;}if (triggered) {print; if ($0 ~ /End pattern/) { exit;}}}' filename

2
perl -ne 'print if (/begin pattern/../end pattern/)' filename

ただし、ファイル全体が出力されます
Herbert

1

ex/ viエディターとglobstarオプションの使用(構文はawkandと同様sed):

ex +"/string1/,/string3/p" -R -scq! file.txt

どこaaaがあなたの出発点でありbbb、あなたの終わりのテキストです。

再帰的に検索するには、次を試してください:

ex +"/aaa/,/bbb/p" -scq! **/*.py

注:**構文を有効にするには、shopt -s globstar(Bash 4またはzsh)を実行します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.