Почему Perl не печатает все совпадения регулярных выражений в одной строке? - PullRequest
0 голосов
/ 26 января 2019

У меня есть регулярное выражение, которое соответствует нескольким строкам внутри строки в текстовом файле.Однако, когда я использую его, чтобы попытаться напечатать все экземпляры захваченной группы, он печатает только первый экземпляр.

Мое регулярное выражение:

/"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 голосов
/ 26 января 2019

Это очень просто.Просто сохраните все совпадения в массиве @x:

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

@ x будет оцениваться (if) как истинное, если оно не пустое.

0 голосов
/ 26 января 2019

Я не вижу OPEN_IT в вашем входном файле.

Попробуйте вместо этого циклы:

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

Круглые скобки дают совпадению контекст списка, для for будет установлено значение $_ для каждого совпадения по одному и вызовется print "$_\n" для каждого.

0 голосов
/ 26 января 2019

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
0 голосов
/ 26 января 2019

Контекст скаляра и списка:

$ 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...