PHP/Regex:bbcode[s]或[strike]的简单Regex无法工作

PHP/Regex:bbcode[s]或[strike]的简单Regex无法工作,php,regex,bbcode,Php,Regex,Bbcode,对于一个愚蠢的bbcode解析器,我想在其中添加两个定义,我最初的定义是preg_替换: '#\[s\](.*?)\[/s\]#si', '<strike>\\1</strike>' 不幸的是,这失败了,而不是你所期望的,[s]和[strike](正确使用)make:s和strike(我的标记正确地显示了它真实的外观结果,它显示了s或strike,不管里面是什么) 为什么它用标记名替换内部文本?我在s | strike的周围添加括号是否有问题?我可能完全错了。问题是您添

对于一个愚蠢的bbcode解析器,我想在其中添加两个定义,我最初的定义是preg_替换:

'#\[s\](.*?)\[/s\]#si', '<strike>\\1</strike>'
不幸的是,这失败了,而不是你所期望的,
[s]
[strike]
(正确使用)make:
s
strike
(我的标记正确地显示了它真实的外观结果,它显示了s或strike,不管里面是什么)


为什么它用标记名替换内部文本?我在s | strike的周围添加括号是否有问题?我可能完全错了。

问题是您添加了两个新的正则表达式组,
(s | strike)
在开始标记中,而
(s | strike)
在结束标记中。因此,在生成的代码中,您将得到
s
strike
。您只需使用正确的组号
2
即可解决此问题

另一种方法是通过在开头添加一个
?:
,使新组成为非引用组,但我想第一种解决方案更容易理解:

\[(?:s|strike)\](.*)\[/(?:s|strike)\]si

BBcode不是常规代码。使用@Gordon:你找错人了。现代正则表达式几乎与常规语言和兼容性类无关。自从Ken Thompson第一次在他的回溯NFA代码中加入
()\1
(grep)以来,正则表达式就不是正则表达式:
()\1
描述的语言在st00pid教科书中的正则性定义中不是正则的,没有人使用,也不适用于现代正则表达式。@Gordon:那篇文章错了!我可以很容易地做出一个他无法打破的模式。他不是在谈论现代正则表达式,只是在谈论教科书上的正则表达式,一些没有人使用的东西。即使是
egrep
也可以匹配
()\1
,这是不规则的。请参见和-&c&c&c@戈登:你不是说不可行;你的意思是不实用,或者也许不是权宜之计。我当然不建议重新发明完美的车轮。我只是厌倦了人们无意识地重复这句老生常谈,“你不能用正则表达式做X”,而他们真正的意思是“我们不知道如何做”、“不要这样做”或“有更简单的方法来实现你的目标”。这是轻蔑、虚伪,甚至是不诚实的。但是Querent一家应该明白,把所有的东西都放在一个正则表达式中并没有道德优势;戈登:恰恰相反,我强烈反对你的观点。高级术语REGULAR的误用与实际模式匹配无关。它有一个高度不规则和完全违反直觉的意思,欺骗任何人,除了一个象牙塔的书呆子。我听腻了你和其他人假装正则表达式是正则表达式。它们不是,甚至要求它们不是:请注意,即使是POSIX BRE也必须支持backref,从而为您所有的常规教皇造假
\((?:[^()]*+|(?0))*\)
是一个漂亮的正则表达式。啊,谢谢,这有助于我的理解。我以为只有
(.*)
才能抓到一个群,我完全忘了
(任何东西)
也可以。编辑:但是第一个
(s | strike)
也组成一个组吗?为什么只是第二个?第一个是\0吗?让我困惑的是,我可能会在睡觉后得到它:PAll
(..)
捕获组(除非它以
?:
开头)。但是组是以
1
开始编号的,因为“组”
0
通常表示整个匹配的字符串(在本例中是
[s]一些文本[/s]
)。哦!!。。现在我完全明白了。谢谢:)命名组也很吸引人(对不起☺) 在
(?…)
中使用。它们也有编号,但首选的访问方式是从模式内部访问
\k
,从外部访问
$+{GROUP\u NAME}
。在一些情况下,您可以引用编号或命名的组,而不使用backref符号。大多数情况下是在
(条件)YES\u PART | NO\u PART)
条件模式的条件测试。您可以编写
((2)…|…)
(…|…)
。还有一些递归测试,您不使用反斜杠来谈论组。命名组优于编号组。
'#\[(s|strike)\](.*?)\[/(s|strike)\]#si', '<strike>\\1</strike>'