Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当我将Perl正则表达式(regex)设置为可选时,它会失败_Regex_Perl - Fatal编程技术网

当我将Perl正则表达式(regex)设置为可选时,它会失败

当我将Perl正则表达式(regex)设置为可选时,它会失败,regex,perl,Regex,Perl,我正在Perl 5.22上运行以下代码片段: DB<41> x "up 34 days, 22:04 and more" =~ m/.*?(?:(\d+) days).*$/ 0 34 DB x“增长34天,22:04及以上”=~m/*(?:(\d+)天)*$/ 0 34 上述代码按预期工作,并从“34天”中抽出34天 当我通过添加一个?最后是这样的: DB<4> x "up 34 days, 22:04 and more" =~ m/.*?(?:(\d+

我正在Perl 5.22上运行以下代码片段:

  DB<41> x "up 34 days, 22:04 and more" =~ m/.*?(?:(\d+) days).*$/
0  34
DB x“增长34天,22:04及以上”=~m/*(?:(\d+)天)*$/
0  34
上述代码按预期工作,并从“34天”中抽出34天

当我通过添加一个?最后是这样的:

  DB<4> x "up 34 days, 22:04 and more" =~ m/.*?(?:(\d+) days)?.*$/
0  undef
DB x“上升34天,22:04及以上”=~m/*?(?:(\d+)天)*$/
0未定义
为什么它不再匹配34?我在网上搜索过,但找不到任何与我匹配的问题(如果你有一个链接来解释,那就太棒了)


提前感谢您的时间。

正则表达式总是从左到右工作;量词总是首先尝试尽可能多地匹配,或者在不贪婪时尽可能少地匹配(比如
*?
)。当它们达到不匹配状态时,只有这样它们才会备份并尝试新的匹配(回溯)。正则表达式的关键是围绕正则表达式引擎将首先尝试的内容展开工作

*?
将首先尝试匹配字符串开头的空字符串,因为这是它能匹配的最小值。在第一个正则表达式的情况下,这不会导致成功的整体匹配,因此它最终会回溯,直到
*?
匹配“up”,以便下面的组可以匹配“34天”。但是,如果您将以下组设置为可选,它将尝试的第一件事是将
*?
的初始模式匹配到空字符串,后跟
(?:(\d+)天)?
匹配空字符串(因为它无法匹配在该特定位置后跟“天”的数字,但它可以匹配空字符串)后跟
*
匹配字符串的其余部分,后跟字符串的结尾;一场成功的比赛


可以很好地可视化行为,以及(注意PCRE与Perl正则表达式不完全相同)。

因为,
*?
(?:(\d+)天)
匹配空字符串,然后匹配任何其他字符串,即整个输入字符串

如果您检查以下内容

use strict;
use warnings;

my $s = "up 34 days, 22:04 and more";

if ($s =~ m/.*?(?:(\d+) days)(.*)$/) {
  print("first:\n  $1=\"$1\"\n  \$2=\"$2\"\n");
}
if ($s =~ m/.*?(?:(\d+) days)?(.*)$/) {
  print("second:\n  \$1=\"$1\"\n  \$2=\"$2\"\n");
}
你会得到

first:
  34="34"
  $2=", 22:04 and more"
second:
  $1=""
  $2="up 34 days, 22:04 and more"

作为输出(还有一个关于
$1
未定义的警告,您可以在这里忽略),它说明了。

您是正确的,它是Perl 5.22,我在我的原始帖子中已经更正。谢谢。请注意,领先的
*?
服务器只会降低比赛速度(可能会降低很多)。删除它(或者在不太可能的情况下使用
^.*.
,您希望主要部分位于
$&
)。