一致する括弧まで grep

一致する括弧まで grep

次のファイルがあります。

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
              }
             }

pcregrepGNUはありませんが、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メモリ内のファイル全体を食べるのと同じです)。

おすすめ記事