8

我一直在工作的网站不会使用 PHP (preg_match) 正则表达式模式匹配数据,这种模式似乎在我测试过的其他任何地方都可以使用。该模式是:

<channel.*?>(.*?)</channel>

它与具有频道标签的 RSS 提要相匹配。

现在我正在处理的服务器只有在将其更改为时才会产生正确的结果:

<channel.*?>(.*)?</channel>

我的正则表达式不是世界上最好的,所以我想知道是否有人可以告诉我这两种模式之间是否有任何显着差异。

小提示:我意识到使用 SimpleXML 等可能会更好,但是这个正则表达式来自以前的应用程序,由于各种原因,我不允许更改它。

提前感谢您的任何见解。

4

4 回答 4

7

该语句(.*)说“选择是零个或多个字符”并且尾随?使其成为可选匹配。相比之下,(.*?)使用的是“懒惰星”(*?),它首先尝试完全跳过匹配。检查以获取更多信息。

要了解普通(贪婪)星和惰性星之间的区别,请查看 PHP 中的以下示例,并注意贪婪星与给出的模式进行最大匹配,而惰性星“放弃”一旦满足匹配模式:

$inputs = array( 'axb' , 'axxxb' , 'axbxb' , 'axbxxxb' );

// GREEDY STAR (NORMAL)
foreach( $inputs as $input )
{
  preg_match( '/a.*b/' , $input , $greedy );
  $greedy_matches[] = $greedy[0];
}

print "<pre>";
print_r( $greedy_matches );
print "</pre>";
/* 
Array
(
    [0] => axb
    [1] => axxxb
    [2] => axbxb
    [3] => axbxxxb
)
*/



// LAZY STAR
foreach( $inputs as $input )
{
  preg_match( '/a.*?b/' , $input , $lazy );
  $lazy_matches[] = $lazy[0];
}

print "<pre>";
print_r( $lazy_matches );
print "</pre>";
/* 
Array
(
    [0] => axb
    [1] => axxxb
    [2] => axb
    [3] => axb
)
*/
于 2012-06-21T14:00:02.077 回答
2

我的猜测是,您实际上并不希望操作员本身变得懒惰。惰性运算符通常会尝试尽可能少地匹配,这在处理大量可能不规则的数据时很可能会产生意想不到的结果。通过将问号放在贪婪组的末尾,您可以向贪婪组添加可选匹配,而不是使组非贪婪(惰性)。如果您想详细了解贪婪和懒惰之间的区别,请查看:http ://www.regular-expressions.info/possessive.html 。

于 2012-06-21T14:01:42.357 回答
0

请提供您尝试匹配的文本示例。

'<channel.*' will match anything starting with <channel

'?>' will match a single character followed by > (so '1>', '2>', 'b>' etc)

如果您想匹配之间的所有内容,只需使用模式

'#<channel>(.*)</channel>#'
于 2012-06-21T14:10:03.777 回答
-1

在正则表达式中, * 表示 0 次或更多次 - 无需添加 ? 在它之后。

编辑:正如我现在从评论中了解到的那样,贪婪有所作为。一个小测试用例:

var_dump(preg_replace('/<channel.*?>(.*?).*<\/channel>/', '$1', '<channel>asd</channel>'));
var_dump(preg_replace('/<channel.*?>(.*)?.*<\/channel>/', '$1', '<channel>asd</channel>'));

输出

string(0) ""
string(3) "asd"

如您所见,我正在使用(.*?).*and (.*)?.*,因此贪婪会有所作为。但是,由于它不一样,在给定的示例中,我看不出它是如何产生影响的。

于 2012-06-21T14:00:19.930 回答