1

在 LaTeX 中,表达式\o{a}{b}意味着运算符 'o' 有两个参数 a 和 b。LaTeX 也接受\o{a},并且在这种情况下将第二个参数视为空字符串。

现在我尝试将正则表达式\\\\o\{([\s\S]*?)\}\{([\s\S]*?)\}与字符串匹配\o{a}\o{a}{b}。当它不是匹配时,它会将整个字符串误认为是匹配的。(对这个字符串的正确解释是子字符串\o{a}{b}是唯一的匹配项。)关键是我需要知道如何告诉 PHP 识别如果在第一个 } 之后有除 { 之外的其他内容,那么它不是匹配项。

我该怎么做?

编辑:运算符的参数允许包含符号\{}。但在这种情况下,整个字符串不匹配的原因是因为大括号中的大括号a}\o{a不符合 LaTeX 规则(例如{必须在 之前}),因此a}\o{a不能作为运算符的参数......

Edit2:另一方面,\o{{a}}{b}应该是一个匹配,因为{a}它是一个有效的参数。

4

3 回答 3

2

我建议这样的事情:

$s = '\\o{a}\\o{a}{b}';
echo "$s\n";  # Check string
preg_match('~\\\o(\{(?>[^{}\\\]++|(?1)|\\\.)+\}){2}~', $s, $match);
print_r($match);

ideone演示

正则表达式:

  • 使用递归来处理嵌套大括号,
  • 也使用反斜杠 ( [^{}\\\]and \\\.) 来避免将文字大括号用作语法大括号。

\\\o             # Matches \o
(                # Recursive group to be
  \{             # Matches {
  (?>            # Begin atomic group (just a group that makes the regex faster)
     [^{}\\\]++  # Any characteres except braces and backslash
  |
     (?1)        # Or recurse the outer group
  |
     \\\.        # Or match an escaped character
  )+             # As many times as necessary
  \}             # Closing brace
){2}             # Repeat twice

您当前正则表达式的问题是,一旦这部分匹配\\\\o\{([\s\S]*?),它将尝试寻找下一个\}即将到来的,并且在那里,您使用的是惰性量词还是贪婪量词都无关紧要。}在实际\}出现在正则表达式之前,您需要以某种方式阻止它匹配。

这就是你必须使用的原因[^{}],因为你实际上可以在里面嵌套大括号,这是使用递归的理想情况。

于 2014-06-11T20:50:17.557 回答
1

要处理可能的嵌套大括号,您需要使用递归功能:

$pattern = <<<'EOD'
~
\\o({(?>[^{}]+|(?-1))*}){2}
~x
EOD;

其中(?-1)是对最后一个捕获组的子模式的引用。

于 2014-06-11T20:41:12.833 回答
0

我猜你需要考虑使用锚点^$

$pattern = '/^\\o\{.*\}(\{.*\})?$/';

我不知道您认为 and 的可接受值是什么ab因此您可以.*在此处替换为适当的类。

这允许使用\0{a}\o{a}{b}格式。要匹配仅\o{a}{b}修改为此:

$pattern = '/^\\o\{.*\}\{.*\}$/';

根据您上次的编辑,我建议将.*上面的内容替换[^{]*为其他答案中所述的内容。

于 2014-06-11T20:32:36.883 回答