正则表达式 (php) 匹配单个 [ 或单个 ],但忽略 [[ ]] 之间的任何内容?

Regex (php) to match single [ or single ] but ignore anything between [[ ]]?

提问人:Richard Taylor 提问时间:4/11/2023 最后编辑:Richard Taylor 更新时间:4/11/2023 访问量:46

问:

我有一个字符串,其中会有 [ ] [[ ]] ][ 的组合,但我需要用 < 和 > 替换单个 [ 和 ],但不要理会(不匹配)[[ ]] 之间的任何内容。

我以为我可以用正则表达式来做到这一点,但我真的很难让它工作,因为目前复杂性超出了我的范围。

示例字符串:

[a] [b]  <- should replace every [ with < and every ] with > so <a> <b>

[a][b]   <- should replace every [ with < and every ] with > so <a><b>

[[abc][a][b]]  <- should not replace anything. will always start with [[ and end with ]]

因此,从逻辑上考虑这个问题,我可以用PHP循环来做到这一点,但是如果可能的话,我真的想尝试使用preg_replace。

据我所知,逻辑是将 [ 替换为 < 和 ] 替换为 [[ 和 ]] 之间的 > EXCEPT 但我不确定我是否可以在正则表达式中做到这一点。我可以通过使用 lookahead/lookbehind 使它部分工作,但这仍然匹配 [[ 和 ]] 之间的 [ 和 ](例如 [[ [a] ]]。

到目前为止,我已经有了

    /(?<!(^|)\[)\[[^\]\[\[]*\]/gmi

努力发现 [a] 而不是 [[a]],但如果我有 [[a [b] c]],则失败。 在这一点上,我不担心替换,我只需要让正则表达式工作以匹配/不匹配。

php 正则表达式 preg-replace 正则表达式替换

评论

1赞 Gilles Quénot 4/11/2023
请看一下如何格式化我的代码块
0赞 user3783243 4/11/2023
g作为修饰符在 PHP 中不起作用。请提供您正在使用的代码。
0赞 user3783243 4/11/2023
将来,您应该提供 regex101 链接,以便我们可以处理您正在使用的内容。我认为 regex101.com/r/PjCOes/1 实现了你的目标
0赞 bobble bubble 4/11/2023
或者这个:\[([^][]*)\]|\[(?:[^][]*(?R)?)*+\](*跳过)(*F)
0赞 bobble bubble 4/12/2023
如果你没有混合字符串,一个基于 \G 的想法:\G[^][]*\K\[([^][]*)\] (如果你没有像这样的字符串,这会更有效,值得一提[[a][b]] [a][b])

答:

0赞 Wiktor Stribiżew 4/11/2023 #1

你可以使用

preg_replace('~(\[\[(?:(?!\[\[|]]).|(?1))*]])(*SKIP)(*F)|\[([^][]*)]~s', '<$2>', $text)

请参阅 PHP 演示和正则表达式演示

细节

  • (\[\[(?:(?!\[\[|]]).|(?1))*]])(*SKIP)(*F)- Group 1:,零次或多次出现任何不是 或 char 序列起点的 char 或整个 Group 1 模式递归,然后 ,一旦找到匹配项,就会跳过它,新的搜索从失败位置开始[[[[]]]]
  • |-或
  • \[([^][]*)]- a ,然后是零个或多个字符,而不是 和 捕获到组 2 中,然后是 .[[]]

评论

1赞 Richard Taylor 4/11/2023
谢谢 Wiktor,这绝对是完美的,我现在看到了 *SKIP 是如何工作的,我只是无法理解。