【问题标题】:PHP PCRE regular expressionPHP PCRE 正则表达式
【发布时间】:2014-08-02 01:07:29
【问题描述】:

在 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} 是一个有效参数。

【问题讨论】:

  • 3 个答案在 21 秒之内。正则表达式忍者今天生效!

标签: php regex latex non-greedy


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 以避免灾难性的回溯,例如,如果缺少右花括号。
    • 您能解释一下这里可能发生的地方吗?
    • 自己做测试,写一个测试字符串(用一个长的第一个参数和几个嵌套的大括号来看看会发生什么)并删除最后一个右大括号。然后比较有和没有原子组的步数。
    • You 和 Jerry 来的正是时候,他在规格中添加了嵌套...... :) +1
    • 好吧,这个主题的步骤没有区别。您只是总是使用原子分组和所有格量词来使事情变得复杂。 但是,你知道为什么!
    【解决方案3】:

    我建议这样:

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

    ideone demo

    正则表达式:

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

    \\\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]*?),它将尝试寻找下一个即将到来的 \},在那里,无论您使用的是惰性量词还是贪婪量词都无关紧要一。在实际的\} 出现在正则表达式之前,您需要以某种方式阻止它与} 匹配。

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

    【讨论】:

    • 你和 Casimir 来的正是时候,他在规格中添加了嵌套...你已经把它覆盖了,所以退出。 :) +1
    • @zx81 谢谢。 LaTeX 可能很棘手,例如您可以使用\binom{\Large{1}}{\tiny{1}},而我总是忘记 PHP 中的反斜杠(在否定类中使用 2 不起作用)。否则,我会更快哈哈 xD 但没关系。
    • 幸好你和 Caz 最重要的是,我不知道 LaTeX 的第一件事(不是避孕套自动售货机???)
    • @zx81 哈哈,不,这是数学渲染语言。你输入\frac{1}{2},你会得到一个不错的“一半”。 \Sigma 给出“求和”符号,你可以得到用\alpha\beta 等显示的希腊字符。换句话说就是数学语言:)
    • Math language in other words 好吧,这也可以防止很多意外怀孕,所以我的猜测不会那么遥远。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多