正则表达式 - 多行报价

时间:2013-05-08 21:24:03

标签: php regex

我遇到了正则表达式的问题:

$var = preg_replace("/\[doxer_quote\]([^]]+)\[\/doxer_quote\]/", '<blockquote>$1</blockquote>', $var);

我试图让它显示blockquote标记内的内容,但我无法弄明白。它也需要经过多行。有人可以帮助我。

2 个答案:

答案 0 :(得分:3)

你的正则表达式适用于[doxer_quote]内不包含“标签”的字符串,例如:

[doxer_quote]my 
  multiline 
  text[/doxer_quote]

但它使用嵌套标签失败,即使是单行内容,例如:

[doxer_quote]my [strong]formatted[/strong] text[/doxer_quote]

原因是您通过重复的字符类]将所有内容与[^]]+字符进行匹配,因此在满足第一个嵌套标记时它会中断。

解决方案:将[^]]+替换为.+,将包含s - 修改为您的正则表达式,即:

$var = preg_replace("/\[doxer_quote\](.+)\[\/doxer_quote\]/s", '<blockquote>$1</blockquote>', $var);

s - 修饰符(称为PCRE_DOTALL)使点匹配任何字符,包括换行符。


处理嵌套元素

如果允许您的标记语言包含嵌套的[doxer_quote]元素,那么它不是regular。正则表达式仅用于处理常规语言。

没有优雅的方式来匹配正则表达式的嵌套元素。想一想以下情况:

[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]”的开头。 (?!)被称为negative lookahead

  • (?:(?!\[doxer_quote\]).)以上分组为non-capturing subpattern

  • (?:(?!\[doxer_quote\]).)+与子模式repeated匹配一次或多次。

  • (?:(?!\[doxer_quote\]).)+? - ?重复量词后+生成量词lazy(也称为非贪婪)。

  • ((?:(?!\[doxer_quote\]).)+?) - 括号定义capturing subpattern。它在替换表达式中由$1引用。

  • 在循环中,每个步骤都会替换最里面的标记。如果字符串在迭代后没有改变,则循环中断。

最后的笔记

  • 如果您确定您的标记始终格式正确(例如,每个开始标记都已关闭)且标记语言的标记不包含属性等,请考虑replacing开始标记并结束直接标记,不匹配内容:

     $var = str_replace(
              array('[doxer_quote]', '[/doxer_quote]'), 
              array('<blockquote>', '</blockquote>'), 
              $var
            ); 
    

    您可以通过这种方式一步处理多个代码(不仅[doxer_quote])。

  • 考虑解析您的标记语言。

答案 1 :(得分:-1)

https://stackoverflow.com/a/2101427/2277620。使用multiline-modifier,但是如果你留下“+”贪婪,你将获得从第一个块开始到最后一个块结束的文本。