【问题标题】:PHP/Regex: simple regex for bbcode [s] or [strike] fails to workPHP/Regex:用于 bbcode [s] 或 [strike] 的简单正则表达式无法正常工作
【发布时间】:2011-05-13 19:12:29
【问题描述】:

对于一个愚蠢的 bbcode 解析器,我想将两个定义合二为一,我原来的定义是 preg_replace:

'#\[s\](.*?)\[/s\]#si', '<strike>\\1</strike>'

这行得通,我希望用户能够使用[s][strike] 来启动该格式的文本,所以我自然地添加了类似这样的内容,认为它会起作用:

'#\[(s|strike)\](.*?)\[/(s|strike)\]#si', '<strike>\\1</strike>'

不幸的是,[s][strike](正确使用)都失败了,而不是你所期望的:sstrike(我的降价是正确显示其真实外观的结果,无论里面是什么,它都会显示 s 或罢工)

为什么它用标签名称代替内部文本?我在 s|strike 周围添加括号有问题吗?我可能做错了..

【问题讨论】:

  • BBcode 不规则。使用BBCode parser
  • @Gordon:你找错树了。现代正则表达式几乎与常规语言和兼容性类无关。自从 Ken Thompson 在grep 中首次将(.)\1 放入他的回溯 NFA 代码中之后,正则表达式就不再是常规的了:(.)\1 描述的语言在 st00pid 教科书 REGULARity 定义中是 not REGULAR使用哪些不适用于现代正则表达式。
  • @Gordon:那篇文章错了! 可以很容易地做出他无法打破的模式。他不是在谈论现代正则表达式,而是在谈论教科书正则表达式,没有人使用的东西。甚至egrep 也可以匹配(.)\1,这不是常规的。见hereherehere——&c&c&c!
  • @Gordon:你不是说不可行;你的意思是不实用,或者可能不方便。我当然不建议重新发明完美的轮子。我只是厌倦了人们漫不经心地重复这种轻描淡写的副歌,“你不能用正则表达式做 X”,当他们 真的 意味着一个或多个 “我们不知道该怎么做”、“不要这样做”或“有更简单的方法可以实现您的目标。”这是轻蔑和不诚实的,甚至是不诚实的。但是询问者应该明白,将所有内容都放入一个正则表达式中并没有道德上的优势。事实上,它有很多缺点。
  • @Gordon:相反,我强烈地和大声地不同意你。高级术语 REGULAR 的误用与真正的模式匹配无关。它具有高度不规则且完全违反直觉的含义,除了象牙塔的蛋头外,它会欺骗任何人。我厌倦了听到你和其他人假装正则表达式是常规的。它们不是,甚至要求它们不是:请注意,即使是 POSIX BRE 也必须支持反向引用,从而使您的所有常规自夸都是谎言。 \((?:[^()]*+|(?0))*\) 是一个漂亮的正则表达式。

标签: php regex bbcode


【解决方案1】:

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

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

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

【讨论】:

  • 啊,谢谢,这有助于我的理解。我以为只有(.*?) 会捕获一个组,我完全忘记了(anything) 也可以。 编辑:但是第一个(s|strike) 也组成一个组吗?为什么只有第二个?是第一个\0?让我感到困惑,但我可能会在睡觉后得到它:P
  • 所有(..) 捕获组(除非它以?: 开头)。但是组以1 开头编号,因为“组”0 通常代表整个匹配的字符串(在本例中为[s]some text[/s])。
  • 哦!!.. 这对我来说完全有意义。谢谢你:)
  • 命名组也很吸引人 (sorry ☺),如 (?&lt;GROUP_NAME&gt; … ) 中所用。它们也有编号,但访问它们的首选方式是模式内部的\k&lt;GROUP_NAME&gt; 和外部的$+{GROUP_NAME}。在某些情况下,您可以引用编号或命名的组,而无需使用 backref 表示法。主要在条件模式的(CONDITION) YES_PART | NO_PART) 条件测试中。你可以写((2)…|…)(&lt;GROUP_NAME&gt;)…|…)。还有一些递归测试你不使用反斜杠来谈论组。命名组优于编号组。
猜你喜欢
  • 2014-11-30
  • 2018-06-02
  • 2012-06-22
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
相关资源
最近更新 更多