2016-04-16 141 views
1

我有文件與發言者被標記的談話序列。我的文件格式是:Perl的正則表達式匹配的東西,但要確保匹配字符串不包含字符串

<SPEAKER>John</SPEAKER> 
I am John 
<SPEAKER>Lisa</SPEAKER> 
And I am Lisa 

我現在正在查明約翰說話,麗莎說右後(然後我想,然後保留文檔的整個部分的每個文檔的第一序列遵循該序列,包括序列)。

我建這個表達式:

^.*?(<SPEAKER>John<\/SPEAKER>.*?<SPEAKER>Lisa<\/SPEAKER>.*)

,但它當然也捕獲那裏是音箱的序列的情況下是約翰 - 邁克爾 - 麗莎,即其中有一個人約翰和麗莎之間說話。

我該如何獲得正確的比賽?

+0

我懷疑你可以爲此做一個(合理的)正則表達式,但它應該很容易在perl程序中使用regexp來做到這一點。 – owler

+1

這是一個合適的XML文檔嗎? – Borodin

+0

你是否想在第一個John-Lisa序列之後捕獲所有東西,而不管它是什麼? (例如,其他約翰 - 麗莎交換,有或沒有中斷。) – zdim

回答

1

這裏是你可以用它來搭配你的描述正則表達式:

(<SPEAKER>John<\/SPEAKER>(?:(?!<SPEAKER>).)*<SPEAKER>Lisa<\/SPEAKER>.*) 

,並顯示一個小的演示,它的工作原理:https://regex101.com/r/iW8vS5/1

但是,因爲這兩個kchinger和owler提到,正則表達式可能不是最好的方式來做到這一點。正則表達式解決方案可能會比任何長文檔的一小段代碼慢得多。

+0

@ rock321987:它看起來是對的。 OP表示他希望發表一個「約翰」演講,然後立即發表一次「麗莎」演講,以及之後的所有內容。 –

+0

@AlanMoore我想我誤解了它 – rock321987

0

這不是一個純粹的正則表達式解決方案,也許別人可以做到這一點,而是我寫了一個小循環來檢查每一行。如果它找到你想要的,它將保留文檔的其餘部分。如果它不是一個完整的文檔,您需要按照正確的順序提供它。執行你想要的正則表達式可能會比較慢,因爲它會比較複雜,但是如果速度很重要,你必須對純正則表達式解決方案進行基準測試(如果有人提出)。

編輯注意:?!如果你還沒有看到它,Lisa是一個負面的向前看。一些合併的負向預測可能是你需要用一個正則表達式來完成的,但是稍後你會看到它。

open(my $input,"input2.txt")||die "can't open the file"; 

my $output = ""; 
my $wanted = 0; 
while(<$input>) 
{ 
    $wanted = 1 if(/<SPEAKER>John<\/SPEAKER>/); 
    $wanted = 2 if(/<SPEAKER>Lisa<\/SPEAKER>/ && $wanted == 1); 
    if(/<SPEAKER>(?!Lisa)/ && /<SPEAKER>(?!John)/ && $wanted == 1) 
    { 
     $wanted = 0; 
     last; 
    } 
    $output = $output . $_ if($wanted); 
} 

print "$output" if $wanted; 
+0

我最終使用這個,但用「$輸出=「」「所以我會caputre第一次互動後發生的所有 – user1769925

+0

感謝您的回答,即使它不是我所要求的 – user1769925

相關問題