2016-09-10 4 views
1

だから、例えば私たちは、ファイルに次き:複数行の正規表現 - 最後の試合の最後に行をスキップする方法

START OF NEW LOG ENTRY 
first line 
second line KEYWORD 
third line 
START OF NEW LOG ENTRY 
first line 
second line 
third line 
etc... (this file goes on in this manner for a long time) 
... 

私はキーワードの単語が含まれている各ログエントリのすべての行を抽出するために必要」キーワード"。これは、以下の(pcregrepを使用して)、対応する正規表現は次のとおりです。

pcregrep -Mo "(?s)(?:^START OF NEW LOG ENTRY)(?:.(?!^START OF NEW LOG ENTRY))*?(?:KEYWORD).*?(?=\nSTART OF NEW LOG ENTRY|\Z)" file 

さて、これはうまく動作し、期待通りに次のように出力されます

START OF NEW LOG ENTRY 
first line 
second line KEYWORD 
third line 

だから、いただきました!間違っていますか? ...まあ、正規表現の仕組みは、そのログエントリ(行1〜4行)をマッチさせた後、正規表現エンジンが2行目から再びマッチしようとするため、正規表現エンジンは不必要に2行分をトラバースします2番目のログエントリの先頭からマッチングを開始するまでに時間がかかるように見えるので、最後のマッチが最後に終了した場所、つまり5行目を続けてください。

\Gを私の正規表現の始まりは((?s)の後に)これ​​を解決するだろうが、そうではない。

スマートなアイデアはありますか?

答えて

0

-oの代わりに-C0を使用してください。

START OF NEW LOG ENTRY 
START 
first line 
second line KEYWORD 
third line 

START 
first line 
second line KEYWORD 
third line 

:それはこのような結果を得た、オプション-oMを使用して

(?s)^START.*?KEYWORD(?:(?!^START).)* 

START OF NEW LOG ENTRY 
first line 
START 
second line KEYWORD 
third line 
START OF NEW LOG ENTRY 
first line 
second line 
third line 
etc... (this file goes on in this manner for a long time) 
... 

...と、この正規表現:私は、この修正された入力を使用して問題を確認しました。 2番目の試合が試合の最終行の後ではなく、2番目の行から開始されることを確認します。必要に応じてオプション-C0 -Mと、それは、ただ一つのヒットを得る:全体ではなく、ラインプラス文脈の一致だものだけを

START OF NEW LOG ENTRY 
START 
first line 
second line KEYWORD 
third line 

-oプリントを。しかし、それはまた、一行に複数のマッチを許し、私はそれが問題の原因だと推測しています。とにかくあなたの正規表現は行全体にマッチするので、コンテキストを抑止するだけです。ここで

は、私が使用する実際の正規表現です:

(?s)^START OF NEW LOG ENTRY(?:(?!^START OF NEW LOG ENTRY|\bKEYWORD\b).)*+\bKEYWORD\b(?:(?!^START OF NEW LOG ENTRY).)*$ 

それは、もう少し効率的だし、それはtempered greedy tokenでエラーを訂正:ドットがない前に、先読み後を行かなければなりません。

関連する問題