【问题标题】:Writing an expression to recursively extract data between parenthesis编写表达式以递归提取括号之间的数据
【发布时间】:2015-05-25 19:48:39
【问题描述】:

我正在尝试编写一个正则表达式来将字符串拆分为匹配的花括号内的单独元素。首先,它需要是递归的,其次,它必须返回偏移量(如PREG_OFFSET_CAPTURE)。

我实际上认为这可能是处理这些数据的一种效率较低的方法,但我不确定一种更简单、更受性能驱动的技术。 (如果你有的话,我很想听听!)

所以,输入可以是这种格式:

Hello {#name}! I'm a {%string|sentence|bit of {#random} text}

如果是这种格式的数据处理就很容易了:

Hello {#name}! I'm a {%string|sentence|bit of random text}

但是在处理方面,问题在于另一组花括号中的递归花括号。 我正在使用以下代码来拆分字符串:

preg_match_all("/(?<={)[^}]*(?=})/m", $string, $braces, PREG_OFFSET_CAPTURE);

如前所述,它非常适合简单的表单。对于更复杂的形式来说,情况就更少了。这样做的目的(我让它以非递归形式起作用)是用函数处理的内容替换每个带括号的区域,向上工作。

理想情况下,我希望能够编写 Hello {#name}! I'm a {%string|sentence|bit of {?(random == "strange") ? {#random} : "strange"}} text} 并使其易于管理。

非常感谢任何帮助。

【问题讨论】:

  • 那么,对于Hello {#name}! I'm a {%string|sentence|bit of {#random} text},您需要捕获{#name}{%string|sentence|bit of {#random} text}{#random}
  • 没错。我也需要理想地捕捉位置!虽然我仍然认为必须有更好的方法来做到这一点,但这需要很长的字符串。
  • 如果您的目标是替换每个括号,则使用递归模式将没有用处。你需要的是替换最里面的括号,直到你的字符串中没有更多的括号。
  • @casimir-et-hippolyte 这很有道理,但我不确定如何实现它。您知道任何可以提供帮助的资源吗?
  • 前瞻技巧的主要问题是它不消耗字符,因此您不能将它与preg_replace 一起使用。一种方法包括定位最内层括号并在while循环中使用preg_replace_callback。看这里:stackoverflow.com/questions/28457853/…

标签: php regex recursion tokenize


【解决方案1】:

您可以利用 PCRE 正则表达式在前瞻和子例程中捕获组的功能来获取嵌套的 {...} 子字符串。

regex demo is available here

$re = "#(?=(\{(?>[^{}]|(?1))*+\}))#"; 
$str = "Hello {#name}! I'm a {%string|sentence|bit of {#random} text}"; 
preg_match_all($re, $str, $matches, PREG_OFFSET_CAPTURE);
print_r($matches[1]);

IDEONE demo

它将返回一个数组,其中包含捕获的类似 {...} 的字符串及其位置:

Array
(
    [0] => Array
        (
            [0] => {#name}
            [1] => 6
        )

    [1] => Array
        (
            [0] => {%string|sentence|bit of {#random} text}
            [1] => 21
        )

    [2] => Array
        (
            [0] => {#random}
            [1] => 46
        )

)

【讨论】:

  • 这解决了我的问题。有没有一种方法也可以被 JavaScript 支持?我正在使用 PHP 来解决这个问题,但我想在某个时候将它移植到 JavaScript。
  • 在 JavaScript 中,不支持正则表达式中的子例程。这意味着,您将无法将嵌套的花括号与正则表达式匹配。
  • 我假设我唯一的选择是某种形式的解析器/词法分析器之类的?
  • 是的,一种状态机。您可能会在 Matching Nested Constructs in JavaScript article at Flagrant Badassery 博客中找到一些很棒的技巧。
  • 我会看看那个。但与此同时,我会让它在 PHP 端正常工作。
猜你喜欢
  • 2018-06-29
  • 2018-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
  • 2011-01-25
  • 1970-01-01
相关资源
最近更新 更多