我遇到了正则表达式的问题:
$var = preg_replace("/\[doxer_quote\]([^]]+)\[\/doxer_quote\]/", '<blockquote>$1</blockquote>', $var);
我试图让它显示blockquote
标签内的内容,但我无法弄清楚。它也需要经过多行。有人可以帮我吗。
您的正则表达式适用于内部不包含“标签”的字符串[doxer_quote]
,例如:
[doxer_quote]my
multiline
text[/doxer_quote]
但它会因嵌套标签而失败,即使是单行内容,例如:
[doxer_quote]my [strong]formatted[/strong] text[/doxer_quote]
原因是你]
通过这个重复的字符类匹配所有的字符:[^]]+
,所以当遇到第一个嵌套标签时它会中断。
解决方案:替换[^]]+
为 a .+
,并将-modified包含s
到您的正则表达式中,即:
$var = preg_replace("/\[doxer_quote\](.+)\[\/doxer_quote\]/s", '<blockquote>$1</blockquote>', $var);
-修饰符s
(称为PCRE_DOTALL)使点匹配任何字符,包括换行符。
如果您的标记语言允许包含嵌套[doxer_quote]
元素,则它不是常规的。正则表达式仅用于处理常规语言。
没有优雅的方法可以通过正则表达式匹配嵌套元素。考虑以下情况:
[doxer_quote]
[doxer_quote]
Lorem ipsum dolor sit amet
[/doxer_quote]
[/doxer_quote]
consetetur sadipscing elitr
[doxer_quote]
sed diam nonumy
[/doxer_quote]
您无法使用单个正则表达式调用来处理它。
但它可以在一个循环中完成,如下所示:
while(($var2 = preg_replace("/\[doxer_quote\]((?:(?!\[doxer_quote\]).)+?)\[\/doxer_quote\]/s", '<blockquote>$1</blockquote>', $var)) !== $var)
$var = $var2;
分步说明:
.
匹配任何字符
(?!\[doxer_quote\]).
匹配任何不是序列“[doxer_quote]”开头的字符。(?!)
称为负前瞻。
(?:(?!\[doxer_quote\]).)
是以上分组为非捕获子模式。
(?:(?!\[doxer_quote\]).)+
匹配重复一次或多次的子模式。
(?:(?!\[doxer_quote\]).)+?
-重复量词?
之后使量词变得懒惰(也称为非贪婪)。+
((?:(?!\[doxer_quote\]).)+?)
- 括号定义了一个捕获子模式。$1
它在替换表达式中被引用。
在循环中,每一步都会替换最里面的标签。如果迭代后字符串没有改变,则循环中断。
如果您确定您的标记始终格式正确(例如,每个开始标记都是关闭的)并且您的标记语言的标记不包含属性等,请考虑直接替换开始标记和结束标记,而不匹配内容:
$var = str_replace(
array('[doxer_quote]', '[/doxer_quote]'),
array('<blockquote>', '</blockquote>'),
$var
);
[doxer_quote]
您可以通过这种方式一步处理多个标签(不仅是)。
考虑解析您的标记语言。
请参阅https://stackoverflow.com/a/2101427/2277620。使用 multiline- 修饰符,但如果你让 "+" 贪心,你会得到从第一个块开始到最后一个块结束的文本。