为什么Perl不打印单行中找到的所有正则表达式匹配项?

时间:2019-01-25 21:29:26

标签: regex perl

我有一个正则表达式,它与文本文件中一行内的多个字符串匹配。但是,当我使用它尝试打印捕获的组的所有实例时,它仅打印第一个实例。

我的正则表达式是:

/"resolution.(\w+)/g

将以下行输入到正则表达式时:

"signalcfg": "{\"signals\":[{\"order\":1,\"id\":\"oryx_C20C0E15-2028-4F4B-A8DD-0DA8D87B4FF9\",\"name\":\"success\",\"rrcodes\":\"resolution.COMPLAINTS_CHANGE_STATUS_SUCCESS\",\"testModule\":\"MCSChangeComplaintsStatus\",\"default\":false},{\"order\":2,\"id\":\"oryx_C943ADB8-6FA2-4DA1-B4D7-24515D96B9DA\",\"name\":\"TimeOut\",\"rrcodes\":\"resolution.MCS_CHANGE_COMPLAINTS_STATUS_TIMEOUT\",\"testModule\":\"MCSChangeComplaintsStatus\",\"default\":false},{\"order\":3,\"id\":\"oryx_0CAC0F97-AD57-4C49-807A-B41839191F74\",\"name\":\"Warning\",\"rrcodes\":\"resolution.MCS_CHANGE_COMPLAINTS_STATUS_WARNING\",\"testModule\":\"MCSChangeComplaintsStatus\",\"default\":false},{\"order\":4,\"id\":\"oryx_4583A3EC-DFC8-47B9-9B04-DEE71DC3F17A\",\"name\":\"APIError\",\"rrcodes\":\"resolution.COMPLAINTS_CHANGE_STATUS_FAIL,resolution.MCS_CHANGE_COMPLAINTS_STATUS_FAIL\",\"testModule\":\"MCSChangeComplaintsStatus\",\"default\":true}]}",

它匹配所有这样的表达式:

"resolution.COMPLAINTS_CHANGE_STATUS_SUCCESS

我已经尝试过打印实例捕获组:

perl -ne 'print "$1\n" if /"resolution.(\w+)/g' FILE_NAME
perl -ne 'print "$1\n" if m/"resolution.(\w+)/sig' FILE_NAME

我希望得到:

OPEN_IT_COMPLAINTS_FOUND
OPEN_IT_COMPLAINTS_NOT_FOUND
MCS_GET_COMPLAINTS_WARNING
MCS_GET_COMPLAINTS_TIMEOUT
MCS_GET_COMPLAINTS_FAIL

但是我只会得到:

OPEN_IT_COMPLAINTS_FOUND

如果我将上述类型的表达式分别放在文件内的一行中,如下所示:

\"rrcodes\":\"resolution.OPEN_IT_COMPLAINTS_NOT_FOUND1\"
\"rrcodes\":\"resolution.OPEN_IT_COMPLAINTS_NOT_FOUND2\"
\"rrcodes\":\"resolution.OPEN_IT_COMPLAINTS_NOT_FOUND2\"
\"rrcodes\":\"resolution.OPEN_IT_COMPLAINTS_NOT_FOUND4\"

我确实得到了预期的输出:

OPEN_IT_COMPLAINTS_NOT_FOUND1
OPEN_IT_COMPLAINTS_NOT_FOUND2
OPEN_IT_COMPLAINTS_NOT_FOUND2
OPEN_IT_COMPLAINTS_NOT_FOUND4

4 个答案:

答案 0 :(得分:2)

if /.../g在标量上下文中使用正则表达式。在这种情况下,/.../g仅返回单个匹配项。下一个/.../g将返回下一个匹配项,等等:

$ perl -ne '
   print "$1\n" if /"resolution.(\w+)/g; 
   print "$1\n" if /"resolution.(\w+)/g;' file
COMPLAINTS_CHANGE_STATUS_SUCCESS
MCS_CHANGE_COMPLAINTS_STATUS_TIMEOUT

如果想要所有匹配项,则必须在标量上下文中重复调用/.../g或在数组上下文中使用它。第一个选项如下所示:

$ perl -ne 'print "$1\n" while /"resolution.(\w+)/g' file
COMPLAINTS_CHANGE_STATUS_SUCCESS
MCS_CHANGE_COMPLAINTS_STATUS_TIMEOUT
MCS_CHANGE_COMPLAINTS_STATUS_WARNING
COMPLAINTS_CHANGE_STATUS_FAIL

在数组上下文/.../g中以数组的形式一次返回所有匹配项,即

@matches = /"resolution.(\w+)/

在某些命令行语句中,可能看起来像这样:

$ perl -ne 'print map { "$_\n" } /"resolution.(\w+)/g' 
COMPLAINTS_CHANGE_STATUS_SUCCESS
MCS_CHANGE_COMPLAINTS_STATUS_TIMEOUT
MCS_CHANGE_COMPLAINTS_STATUS_WARNING
COMPLAINTS_CHANGE_STATUS_FAIL

答案 1 :(得分:1)

标量vs.列表上下文:

$ perl -ne 'print "$_\n" foreach (/"resolution\.(\w+)/g)' dummy.txt
COMPLAINTS_CHANGE_STATUS_SUCCESS
MCS_CHANGE_COMPLAINTS_STATUS_TIMEOUT
MCS_CHANGE_COMPLAINTS_STATUS_WARNING
COMPLAINTS_CHANGE_STATUS_FAIL

/g仅在正则表达式被重复执行时才返回多个结果。您的命令行只执行一次匹配。

也许下面的代码示例使其更加清晰;

#!/usr/bin/perl
use strict;
use warnings;

my $re    = qr/string\.(\w+)/;
my $input = "asdlkj string.TEST1 daklkl string.TEST2 kasöldk";

my($scalar) = ($input =~ /$re/g);
print "SCALAR: $scalar\n";

my @array   = ($input =~ /$re/g);
print "ARRAY:  @array\n";

exit 0;

答案 2 :(得分:1)

在您的输入文件中看不到OPEN_IT。

尝试遍历比赛:

perl -ne 'print "$_\n" for (/"resolution.(\w+)/g)' FILE_NAME

括号为匹配项提供一个列表上下文,for会一次将$_设置为每个匹配项,并在每个匹配项上调用print "$_\n"

答案 3 :(得分:1)

这很容易。只需将所有匹配项保存在数组@x中:

perl -ne 'say join "\n",@x if @x=/\"resolution.(\w+)/g' FILE_NAME

如果

@x不为空,则它将被if评估为true。