簡體   English   中英

使用perl中的regex匹配上次出現的事件

[英]Match from last occurrence using regex in perl

我有這樣的文字:

hello world /* select a from table_b
*/ some other text with new line cha
racter and there are some blocks of 
/* any string */ select this part on
ly 
////RESULT rest string

文本是多行的,我需要從最后一次出現的“* /”中提取,直到“//// RESULT”。 在這種情況下,結果應該是:

 select this part on
ly 

如何在perl中實現這一目標?

\\\\\\*/(.|\\n)*////RESULT但是從第一個“* /”開始

在這種情況下,一個有用的技巧是在regexp前加上貪婪模式.* ,它會在模式的其余部分匹配之前嘗試匹配盡可能多的字符。 所以:

my ($match) = ($string =~ m!^.*\*/(.*?)////RESULT!s);

讓我們將這種模式分解為其組成部分:

  • ^.*從字符串的開頭開始,並盡可能多地匹配字符。 s修飾符允許.甚至匹配換行符。)字符串開頭的錨點^不是絕對必要的,但它確保正則表達式引擎在匹配失敗時不會浪費太多時間回溯。

  • \\*/只匹配文字字符串*/

  • (.*?)匹配並捕獲任意數量的字符; ? 使它不合適,所以它更喜歡匹配盡可能少的字符,以防有一個以上的位置,其余的正則表達式可以匹配。

  • 最后, ////RESULT只是匹配自己。

由於該模式包含很多斜線,並且因為我想避免傾斜牙簽綜合症 ,所以我決定使用替代的regexp分隔符。 感嘆號( ! )是一種流行的選擇,因為它們不會與任何正常的正則表達式語法沖突。


編輯:下面與ikegami的討論,我想我應該注意,如果你想在更長的正則表達式中使用這個正則表達式作為子模式,並且如果你想保證匹配的字符串(.*?) 永遠不會包含////RESULT ,那么你應該將regexp的那些部分包裝在一個獨立的(?>)子表達式中 ,如下所示:

my $regexp = qr!\*/(?>(.*?)////RESULT)!s;
...
my $match = ($string =~ /^.*$regexp$some_other_regexp/s);

(?>)導致其中的模式失敗而不是接受次優匹配(即超出匹配////RESULT的第一個子串的匹配),即使這意味着正則表達式的其余部分將無法匹配。

(?:(?!STRING).)*

匹配任意數量的不包含STRING的字符。 它就像[^a] ,但是對於字符串而不是字符。

如果您知道不會遇到某些輸入(如Kenosis和Ilmari Karonen所做的那樣),您可以使用快捷方式,但這與您指定的內容相符:

my ($segment) = $string =~ m{
    \*/
    ( (?: (?! \*/ ). )* )
    ////RESULT
    (?: (?! \*/ ). )*
    \z
}xs;

如果您不關心*/ ////RESULT之后是否出現*/ ,則以下是最安全的:

my ($segment) = $string =~ m{
    \*/
    ( (?: (?! \*/ ). )* )
    ////RESULT
}xs;

如果有兩個////RESULT跟隨最后一個*/ ,則沒有指定會發生什么。 以上匹配直到最后一個。 如果你想匹配到第一個,你可以使用

my ($segment) = $string =~ m{
    \*/
    ( (?: (?! \*/ | ////RESULT ). )* )
    ////RESULT
}xs;

這是一個選項:

use strict;
use warnings;

my $string = <<'END';
hello world /* select a from table_b
*/ some other text with new line cha
racter and there are some blocks of 
/* any string */ select this part on
ly 
////RESULT
END

my ($segment) = $string =~ m!\*/([^/]+)////RESULT$!s;

print $segment;

輸出:

 select this part on
ly 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM