【问题标题】:PHP regular expression if escaped parenthesis exist如果存在转义括号,则 PHP 正则表达式
【发布时间】:2015-10-22 19:28:57
【问题描述】:

在 PHP 中,我试图完成一个简单的任务,即使用 preg_match_all 从字符串中提取一些信息

我有一个这样的字符串,例如0(a)1(b)2(c)3(d)4(e)5(f)

我正在尝试返回每个 () 内部的所有内容,但尊重其中可能存在转义括号的事实。

我尝试了多种组合,但我无法获得任何正则表达式来允许类似 4(here are some escaped parens\(\) more text) 的东西返回这个 here are some escaped parens\(\) more text 而不是这个 here are some escaped parens\(\)

我有一个有效的正则表达式,但不能使用转义括号

[0-9]*\(([^ESCAPED PARENTHESIS])*?\)

有人可以告诉我如何做到这一点吗?

【问题讨论】:

  • 你需要寻找/\\\(/。前两个反斜杠将解析为单个文字反斜杠,\( 将成为常规括号,不捕获任何内容。

标签: php regex escaping


【解决方案1】:

您可以使用negative look behind 使您的正则表达式引擎只匹配不带反斜杠的右括号:

\((.+?)(?<!\\)\)

查看演示https://regex101.com/r/oU9sF2/1

Debuggex Demo

【讨论】:

  • 完美!我正在研究其他堆栈溢出问题的负面看法,但我无法正确实现它,因为这些示例是针对字符串的,我不太了解它是如何工作的。这绝对帮助我弄清楚了。只要允许,我就会把它算作答案。
  • 我的正则表达式几乎快两倍。这里不需要后视,它只会影响性能。
  • @SpencerMay 您还可以查看有关环顾四周的相关链接以了解有关此主题的更多信息。
  • 我现在只依赖两件事:1)在 regex101.com 上完成匹配的步骤数,2)惰性点匹配从未比基于否定字符类的解决方案更快。另外,your regex will fail here,当最后的 ) 前面有两个反斜杠时,表示 1 个文字反斜杠(与 anubhava 相同)。
  • @SpencerMay - 请注意不要在括号目标末尾添加双反斜杠(转义反斜杠??)\\,因为这会破坏这个正则表达式 - 例如0(a)1(wordsending in backslash \\)2(b)3(c)
【解决方案2】:

您可以使用此正则表达式来匹配您的文本:

preg_match_all('/(?<!\\)\((.*?)(?<!\\)\)/', $str, $matches);

print_r($matches[1]);

RegEx Demo

【讨论】:

    【解决方案3】:

    你可以使用这个模式:

    $pattern = <<<'EOD'
    ~[0-9]+\([^)\\]*+(?s:\\.[^)\\]*)*+\)~
    EOD;
    

    demo

    这个想法是匹配所有字符,直到右括号和反斜杠。当到达反斜杠时,下一个字符也被匹配,并且“und so weiter”等,直到世界末日(或右括号),所有不是右括号或反斜杠的字符都被匹配。

    注意:所有格量词*+ 仅用于在没有右括号时限制回溯。

    【讨论】:

      【解决方案4】:

      这是一个有效的正则表达式:

      [0-9]*\(([^()\\]*(?:\\.[^()\\]*?)*)\)
      

      regex demo

      IDEONE demo:

      $re = '~[0-9]*\(([^()\\\\]*(?:\\\\.[^()\\\\]*?)*)\)~s'; 
      $str = "0(a)1(b)2(c)3(d)4(here are some escaped parens\(\) more text)5(f)"; 
      preg_match_all($re, $str, $matches);
      print_r($matches[1]);
      

      正则表达式分解:

      • [0-9]* - 匹配 0 个或多个数字
      • \( - 匹配文字 (
      • ([^()\\]*(?:\\[()][^()]*?)*) - 匹配和捕获
        • [^()\\]* - 除了\() 之外的 0 个或多个符号
        • (?:\\.[^()]*?)* - 匹配 0 个或多个...
          • \\. - 转义字符后跟
          • [^()\\]*? - 除了\() 之外,尽可能少的字符
      • \) - 匹配文字 )

      【讨论】:

      • 我回滚了,现在不会了。
      • hmmmmmmm - 不知道为什么我将你的正则表达式粘贴到那里 - 现在它在 \) (see regex101) 上中断了
      • 不要相信@CodeJockey cmets(对不起),因为这些示例字符串是错误的(当您想在 regex101 中转义主题字符串中的某些内容时,您只需要一个反斜杠,而不是两个)。
      • @CodeJockey: 是的,在主题字符串中\\) 不是转义的右括号,它是一个转义的反斜杠,后跟一个右括号(非转义)。
      • @CasimiretHippolyte 正确 - 在对所选答案的评论中,stribizhev 指出正确的右括号之前的转义反斜杠 (\\) 会破坏表达式(也就是说,另一个表达式会已经看到括号前的斜线并忽略它作为转义,即使它本身已经转义)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2016-08-12
      • 1970-01-01
      • 1970-01-01
      • 2023-01-11
      相关资源
      最近更新 更多