2012-02-04 152 views
2

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

一些文本“被捕获”一些文字“被捕获”一些 文字

这是可以预见的是界定文本标记被捕获的唯一的东西。捕获的文本本身每次都不相同。最后,我需要把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并不能解决这个问题,可能我也必须更改正则表达式本身,但我不知道如何。

回答

3

你试过preg_replace吗?

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

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

$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); 
+0

这将匹配''一些更多的文本'',这是无意的。 – Grilse 2012-02-04 21:39:22

+0

@Grilse它不是从问题开始。 '唯一可以预测的是划定要捕获的文本的标记。' – Cheery 2012-02-04 21:42:16

+0

让我改述一下: 如果有两个以上的分隔符,那么这也将与分隔符2和3之间的任何文本匹配,这是无意识的。 – Grilse 2012-02-04 21:54:57

0

当你基本上要捕捉一切,但有你的特定部分分离,那么你可能能够使用preg_split

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

的诀窍就是国旗。你将不得不遍历结果数组。每一秒都是你用正则表达式指定的。其余的是中间部分。

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> 

::编辑:: 这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; 
1

您的代码无法正常工作的主要原因是第三组(.*)在第一个引用部分之后吞噬了所有内容,包括所有剩余的引号。如果.与换行符相匹配,则会在文档的其余部分中使用所有引号,而不仅仅是该行的其余部分。

@ Cheery的解决方案通过使第三组非贪婪:(.*?)来解决该问题。这将起作用,但仅仅是因为第三组从未捕获任何东西。它不是消耗一切,而是消耗一切。这是可以接受的,然后在正则表达式中没有什么能够强制它消耗更多,所以它在那里停止。

解决这个问题的正确方法是通过匹配只有你想要突出的部分。使用捕获组把它放回去与周围的标签,并独自离开了文本的其余部分:

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

事实上,你甚至不需要使用捕获组。由于比赛现在只包括引用部分,你可以使用$0重新插入它:

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

编辑: @Cheery编辑他的答案和我的意见它不再适用。我认为这个答案仍然增加了一些价值,所以我会继续前进并放弃它。