正则表达式不会获取嵌套的花括号

时间:2017-03-08 07:58:26

标签: regex perl

有时大括号匹配,在少数情况下不会。

我的代码:

use strict;
use warnings;

my $str1 = '$$\eqalign{&\cases{\mathdot{\bf x}=A{\bf x}+Bu\cr y=H{\bf x}}\quad{\rm with}\{\bf x}=\left(\matrix{x\cr\mathdot{x}\cr\theta\cr\mathdot{\theta}}\right),\cr&A\!=\!\!\left(\matrix{0&1&0&0\cr 0&0&-{m_{a}\over M}g&0\cr 0&0&0&1\cr 0&0&{(M\!+\!m_{a})\over Ml}g&0}\right)\!,\ B\!=\!\left(\matrix{0\cr{a\over M}\cr 0\cr-{a\over Ml}}\right)\!,\ H^{T}\!=\!\left(\matrix{1\cr 0\cr 1\cr 0}\right)\!.}$$';

my $str2 = "\\bibcite{Airdetal2013}{{2}{2017}{{{John} {et~al.}}}{{{James}, {Flexi}, {Buella}, {Curren}, {Mozes}, {Sam}, {Kandan}, {Alexander}, {Alfonsa}, {Fireknight}, {Georgen}, {Karims}, {Merloni}, {Nanda}, {Terra}, {Alvato}, {Nini}, {Winski}, {Shankar}, {Gnali}, \& {Giito}}}}";

my $regex = qr/(?:[^{}]*(?:{(?:[^{}]*(?:{(?:[^{}]*(?:{[^{}]*})*[^{}]*)})*[^{}]*)*})*[^{}]*)*/;

if($str1=~m/\{$regex\}/) {  print "str1: $&\n";  }
if($str2=~m/\{$regex\}/) {  print "str2: $&\n";  }


OUTPUT:

str1: {&\cases{\mathdot{\bf x}=A{\bf x}+Bu\cr y=H{\bf x}}\quad{\rm with}\ {\bf x}=\left(\matrix{x\cr\mathdot{x}\cr\theta\cr\mathdot{\theta}}\right),\cr&A\!=\!\!\left(\matrix{0&1&0&0\cr 0&0&-{m_{a}\over M}g&0\cr 0&0&0&1\cr 0&0&{(M\!+ !m_{a})\over Ml}g&0}\right)\!,\ B\!=\!\left(\matrix{0\cr{a\over M}\cr 0\cr-{a\over Ml}}\right)\!,\ H^{T}\!=\!\left(\matrix{1\cr 0\cr 1\cr 0}\right)\!.}

str2: {2}

str1 is correct output. str2 incorrect output.

Expected Output on str2 is:

 str2: {{2}{2017}{{{John} {et~al.}}}{{{James}, {Flexi}, {Buella}, {Curren}, {Mozes}, {Sam}, {Kandan}, {Alexander}, {Alfonsa}, {Fireknight}, {Georgen}, {Karims}, {Merloni}, {Nanda}, {Terra}, {Alvato}, {Nini}, {Winski}, {Shankar}, {Gnali}, \& {Giito}}}}
  

在示例中,str1字符串与嵌套的花括号不匹配。但是第二个样本str12字符串可以匹配嵌套的花括号。

这是我的问题可以匹配嵌套的花括号。我很无能为力。如果有人指出我的错误会更好。

提前致谢。

2 个答案:

答案 0 :(得分:2)

注意问题中的修改会在前面添加\\bibcite{Airdetal2013}。但是,这不会改变下面的分析,因为它不会改变整体嵌套级别。

必须以更好的方式做到这一点。 Wiktor Stribiżew在评论中提供了递归正则表达式。有用于递归解析的模块。还有解析Latex的工具。

然而,出于好奇......

你的字符串,适当缩短

my $str2 = "{{2}{2017}{{{John}{et~al.}}}{{{James}, ... {Gnali}, \& {Giito}}}}";

或者,C代表一对有内部物品的曲线(没有嵌套)

"{ C C { { C C } { C, ... \& C } } }"

所以你有三个级别的嵌套,以达到最后一对{...}(没有进一步的嵌套)。

你的正则表达式,与$nc = qr/[^{}]*/(非卷曲)展开,以便我们可以查看它

my $regex = qr/
    (?: $nc 
        (?: { 
            (?: $nc 
                (?: { 
                    (?: $nc (?: { $nc } )* $nc ) 
                    } 
                )* $nc 
            )* 
            } 
        )* $nc 
    )*/x;

我可以在这里算两个级别。 ($nc没有curlies,因此{ $nc }与我上面的C匹配。)

因此这个正则表达式不能匹配整个字符串。

如何解决?最好,找到另一种方式,以免淹没在这。

或者,像上面那样写出来,非常小心,并添加缺失的等级。

答案 1 :(得分:2)

由于您的实际要求(discussed in the chat)要匹配以Application.DisplayAlerts = True开头的子字符串,后跟\bib子字符串或除{...}{以外的任何字符,你应该使用带有子程序的正则表达式

}

<强>详情:

  • /\\bib(?:({(?:[^{}]++|(?1))*})|(?!\\bib)[^{}])*/g - \\bib文字文字
  • \bib - 出现以下情况:
    • (?:({(?:[^{}]++|(?1))*})|(?!\\bib)[^{}])* - 第1组(将使用({(?:[^{}]++|(?1))*})递归)匹配
      • (?1) - 文字{
      • { - 除(?:[^{}]++|(?1))*{或整个第1组子模式之外的0个或多个1个字符出现
      • } - 文字}
    • } - 或
    • | - (?!\\bib)[^{}]{之外的字符不会启动}字面字符序列。

请参阅sample Perl code

\bib