多个正则表达式捕获

时间:2012-02-04 21:28:39

标签: php regex

我需要多次捕获某个模式,同时还要记住之前,之后和之间的内容。例如:

  

一些文字“被捕获”更多的文字“被捕获”了一些   文本

唯一可以预测的是分隔要捕获的文本的标记。捕获的文本本身每次都不同。最后,我需要在捕获的部分周围放置CSS跨度,如此

some text <span class="a">"to be captured"</span> some more text <span
class="a">"to be captured"</span> some more text

我试过

if (preg_match("/(.*?)(\".*?\")(.*)/", $line, $m)
    $res .= $m[1] . '<span class="a">' . $m[2] . '</span>' . $m[3];

它适用于只有一次捕获的线。使用preg_match_all并不能解决这个问题,可能我还需要更改正则表达式本身,但我不知道如何。

4 个答案:

答案 0 :(得分:3)

您尝试过preg_replace吗?

$line = preg_replace("/(\".*?\")/", 
                    '<span class="a">$1</span>',
                    $line
);

ps:我还不确定OP的问题是什么,没有例子。如果你有一组分隔符,那么regexp可能是

$str = 'some text "to be captured" some more text #to be *captured# 
            some more text* but I would capture that*';
echo preg_replace('/(("|#|\*).*?\\2)/s', 
                    '<span class="a">$1</span>',
                    $str); 

答案 1 :(得分:1)

我不了解PHP,但仅查看正则表达式,您需要搜索此内容:([^"]*)(".*?")并替换为此$1<span class="a">$2</span>

some text "to be captured" some more text "to be captured" some more text
some text "to be captured" some more text "to be captured"

会给出这个:

some text <span class="a">"to be captured"</span> some more text <span class="a">"to be captured"</span> some more text
some text <span class="a">"to be captured"</span> some more text <span class="a">"to be captured"</span>

:: EDIT :: 这个PHP代码似乎正在运行:

$line = 'some text "to be captured" some more text "to be captured" some more text';

$line2 = preg_replace('/([^"]*)(".*?")/', htmlspecialchars('$1<span class="a">$2</span>'),$line);

echo $line2;

答案 2 :(得分:1)

您的代码无效的主要原因是第三组(.*)吞噬了第一个引用部分之后的所有内容,包括所有剩余的引号。如果.匹配换行符,它会占用文档其余部分的所有引号,而不仅仅是行的其余部分。

@ Cheery的解决方案通过使第三组非贪婪来解决这个问题:(.*?)。这将有效,但只是因为第三组从未捕获任何东西。它不是消耗它所能做的一切,而是从没有消耗任何东西开始。这是可以接受的,并且在正则表达式之后没有任何东西可以强迫它消耗更多,所以它就会停在那里。

解决此问题的正确方法是仅匹配 要突出显示的部分。使用捕获组将其放回到其周围的标签中,并将剩余的文本单独留下:

$line = preg_replace('/("[^"]*")/', '<span class="a">$1</span>', $line);

事实上,您甚至不需要使用捕获组。由于匹配现在仅包含引用的部分,因此您可以使用$0重新插入它:

$line = preg_replace('/"[^"]*"/', '<span class="a">$0</span>', $line);

编辑: @Cheery编辑了他的答案,我的评论不再适用。我认为这个答案仍然会增加一些价值,所以我会继续把它留下来。

答案 3 :(得分:0)

如果您基本上想要捕获所有内容,但将特定部分分开,那么您可以使用preg_split

 $matchs_and_in_between = preg_split('/"(.*?)"/', $src,
                          PREG_SPLIT_DELIM_CAPTURE);

诀窍是旗帜。而且你必须遍历结果数组。每个第二个条目都是您使用正则表达式指定的条目。其余的是中间部分。