提问人:Richard Taylor 提问时间:4/11/2023 最后编辑:Richard Taylor 更新时间:4/11/2023 访问量:46
正则表达式 (php) 匹配单个 [ 或单个 ],但忽略 [[ ]] 之间的任何内容?
Regex (php) to match single [ or single ] but ignore anything between [[ ]]?
问:
我有一个字符串,其中会有 [ ] [[ ]] ][ 的组合,但我需要用 < 和 > 替换单个 [ 和 ],但不要理会(不匹配)[[ ]] 之间的任何内容。
我以为我可以用正则表达式来做到这一点,但我真的很难让它工作,因为目前复杂性超出了我的范围。
示例字符串:
[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]],则失败。 在这一点上,我不担心替换,我只需要让正则表达式工作以匹配/不匹配。
答:
0赞
Wiktor Stribiżew
4/11/2023
#1
你可以使用
preg_replace('~(\[\[(?:(?!\[\[|]]).|(?1))*]])(*SKIP)(*F)|\[([^][]*)]~s', '<$2>', $text)
细节:
(\[\[(?:(?!\[\[|]]).|(?1))*]])(*SKIP)(*F)
- Group 1:,零次或多次出现任何不是 或 char 序列起点的 char 或整个 Group 1 模式递归,然后 ,一旦找到匹配项,就会跳过它,新的搜索从失败位置开始[[
[[
]]
]]
|
-或\[([^][]*)]
- a ,然后是零个或多个字符,而不是 和 捕获到组 2 中,然后是 .[
[
]
]
评论
1赞
Richard Taylor
4/11/2023
谢谢 Wiktor,这绝对是完美的,我现在看到了 *SKIP 是如何工作的,我只是无法理解。
评论
g
作为修饰符在 PHP 中不起作用。请提供您正在使用的代码。:[^][]*(?R)?)*+\](*跳过)(*F)
G
[^][]*\K\[([^][]*)\] (
如果你没有像这样的字符串,这会更有效,值得一提[[a][b]] [a][b]
)