这些正则表达式模式是否不同


Are these regex patterns different?

我一直在研究的网站不会使用 PHP (preg_match) 正则表达式模式匹配数据,该模式似乎在我测试过的其他任何地方都有效。该模式为:

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

它与具有频道标记的 RSS 源匹配。

现在,我正在使用的服务器只有在将其更改为以下情况下才会产生正确的结果:

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

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

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

提前感谢您的任何见解。

语句

(.*)说"所选内容为零个或多个字符",尾随?使其成为可选匹配项。 相比之下,(.*?)使用的是"懒惰星"(*?),它首先尝试完全跳过比赛。 查看此内容以获取更多信息。

要理解正常(贪婪)星和懒惰星之间的区别,请查看 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
)
*/

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

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

'<channel.*' will match anything starting with <channel
'?>' will match a single character followed by > (so '1>', '2>', 'b>' etc)

如果您想匹配两者之间的所有内容仅使用模式

'#<channel>(.*)</channel>#'

在正则表达式中,* 表示 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"

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