次のファイルがあります。
pin(ABC) {
a b c d e f {
abc
}
}
pin(XYZ) {
g h i j k {
j k {
cg {
}
}
}
}
abcd pqrs rstu
mango banana tree
pin(PQR) {
mango
}
それでは、次のようにテキストをgrepしたいと思います。 -
ABCを入力として使用する場合、出力は以下のように「pin(ABC){」で始まり、一致する角括弧「}」までの内容を含むABCというファイルでなければなりません。
pin(ABC) {
a b c d e f {
abc
}
}
PQRを提供する場合、出力は次の内容を含むPQRというファイルでなければなりません。
pin(PQR) {
mango
}
ちょっと待って、pin()内の単語の
1つの方法は、「pin(ABC)から次の名前「pin」でテキストをgrepし、出力を「ABC」というファイルに送信することです。ABCが次の場合にのみ機能します。しかし、PQRとXYZのケースで失敗しました。
答え1
$ pcregrep -Mo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
pin(ABC) {
a b c d e f {
abc
}
}
pcregrep
GNUはありませんが、PCREgrep
モードをサポートするように構築されていて、ファイルが大きすぎず、NUL文字を含まない場合は、次のことができます。
grep -zPo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
これら(pcregrep
およびgrep -P
)は、再帰正規表現演算子をサポートするPCREモードを使用します。
pcregrep -M
複数行モードをオンにして(pcregrep
正規表現を一致させるときに必要に応じて複数行を取得できます)、grep -z
代わりにレコードをNULで区切るように指示します。ワイヤー。
上記のトリックは(?1)
演算子にあります。つまり、内部正規表現最初パレングループしたがって、我々は再帰的な正規表現を持っています:私たちは、ゼロ以上の()中括弧ではない文字(、所有権バージョンです)のシーケンスが続くシーケンス{
と一致します。*
[^{}]++
++
+
または再び外部正規表現(...)
({
後ろに...)を使用します。
pcrepattern
詳しくはマニュアルページをご覧ください。これはそこの例からほぼそのままコピーされました。
使用perl
:
perl -l -0777 -ne 'print $& while /pin\(ABC\) (\{([^{}]++|(?1))*\})/g'
(grep
メモリ内のファイル全体を食べるのと同じです)。