簡體   English   中英

使用遞歸正則表達式(如 perl)匹配 Ruby 中的平衡括號

[英]Matching balanced parenthesis in Ruby using recursive regular expressions like perl

我一直在尋找一種在正則表達式中匹配平衡括號的方法,並在 Perl 中找到了一種使用遞歸正則表達式的方法:

my $re;
$re = qr{
           \(
              (?:
                 (?> [^()]+ )       # Non-parens without backtracking
                 |
                 (??{ $re })        # Group with matching parens
              )*
           \)
         }x;

來自perl 正則表達式站點

有沒有辦法在 Ruby 或類似的語言中做到這一點?

更新

對於那些感興趣的人,這里有一些有趣的鏈接:

Oniguruma 手冊- 來自 Sawa 的回答。

務實程序員Ruby 1.9 正則表達式示例篇

是的。 使用內置於Ruby 1.9 並且可安裝在 Ruby 1.8 中的 oniguruma 正則表達式引擎,您可以做到這一點。 您使用(?<name>...)(?'name'...)命名子正則表達式。 然后在同一個正則表達式中調用帶有\g<name>\g'name'的子正則表達式。 因此,您的正則表達式轉換為 oniguruma 正則表達式將是:

re = %r{
  (?<re>
    \(
      (?:
        (?> [^()]+ )
        |
        \g<re>
      )*
    \)
  )
}x

另請注意,PHP >=5 中的多字節字符串模塊使用 oniguruma 正則表達式引擎,因此您也可以這樣做。

oniguruma 的手冊在這里

我喜歡上述解決方案,但經常希望忽略轉義字符。 假設 \ 轉義了以下字符,則以下正則表達式也處理轉義字符。

ESC= /(?<![\\])(?>[\\](?:[\\][\\])*)/
UNESC= /(?:\A|(?<=[^\\]))(?:[\\][\\])*/
BALANCED_PARENS = /#{UNESC}(
                   (?<bal>\(
                    (?>
                      (?>  (?:#{ESC}\(|#{ESC}\)|[^()])+     )
                      |\g<bal>
                    )*
                    \))    ) /xm

鑒於負向后視的限制,由匹配括號分隔的部分將是第一個捕獲而不是整個匹配(整個匹配可能包含前導轉義的反斜杠)。

ESC 和 UNESC 復雜的原因是假設 \\ 是轉義的反斜杠。 我們只在初始括號匹配之前使用 UNESC 序列,因為任何其他轉義括號都將在原子組內匹配並且永遠不會回溯。 實際上,如果我們嘗試將 UNESC 前綴用於內部或最終括號匹配,那么當原子組內的 [^()] 匹配前導 \ 並拒絕回溯時,它將失敗。

此正則表達式將掃描界定有效平衡括號的第一個括號。 因此,給定字符串“((東西)”,它將匹配“(東西)”。通常,所需的行為是定位第一個(未轉義的)括號,或者匹配內部(如果平衡)或不匹配。不幸的是,原子分組不會阻止整個正則表達式退出並在稍后嘗試匹配,因此我們必須錨定在字符串的開頭並且只查看第一次捕獲。以下正則表達式進行了此更改:

BALANCED_PARENS = /\A(?:#{ESC}\(|#{ESC}\)|[^()])*+
                  (?<match>\(
                   (?<bal>
                    (?>
                      (?>  (?:#{ESC}\(|#{ESC}\)|[^()])+     )
                      |\(\g<bal>
                    )*
                    \))    ) /xm

暫無
暫無

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

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