Regex / Preg_replace,改变搜索点

时间:2012-03-09 11:23:43

标签: regex preg-replace

我有一个看似简单的正则表达式问题,我似乎无法弄清楚!

这是我开头的表达式:

## a ## 
text1
## b ## 
text2
## c ## 
text3

这就是我想要完成的事情:

<text title="a">
text1
</text>

<text title="b">
text2
</text>

<text title="c">
text3
</text>

到目前为止,这是我尝试过的:

preg_replace ('/##(.*?)##(.*?)##/s', '<text title="$1">$2</text>==', $data);

我遇到的问题是preg_replace从最后一场比赛结束时重新开始搜索,有没有办法改变这个?

或者,如果我的策略很糟糕,那么最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

您的问题是第一个匹配消耗了表达式中的最后一个##,因此它与下一个匹配项不匹配。

您可以使用前瞻来避免这种情况。像这样:

/##(.*?)##(.*?)(?=##)/s

但你可能想要更像的东西:

/^## *([^#]+?) *##$(.*?)(?=^##[^#]+##$|\z)/ms

答案 1 :(得分:0)

正如Qtax指出的那样,每场比赛都会消耗##本来应该是下一场比赛。切换到前瞻有帮助,但你仍然需要处理最后一场比赛的特殊情况。但我认为你甚至不需要在下一行,更不用说消耗它了。看看这个:

$result = preg_replace('/^## *(.*?) *##\s+(.*)/m',
                       "<text title='$1'>\n$2\n</text>\n",
                       $subject);

这是 demo

我做的最重要的改变是放弃s修饰符。只有一个地方需要一个点来匹配换行符,我使用\s+来匹配它。如果没有s修饰符,我可以安全地使用(.*)来使用第二行。作为奖励,我知道(.*?)无法逃脱第一行的限制(只有在输入格式错误时才会发生)。