Reputation: 31
I have a regex that matches multiple Strings inside a line in a text file. However, when I use it to try to print all the instances of the captured group it is only printing the first instance.
My regex is:
/"resolution.(\w+)/g
When feeding the following line to the regex:
"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}]}",
It matches all expressions like this:
"resolution.COMPLAINTS_CHANGE_STATUS_SUCCESS
I've tried this to print the instances capturing group:
perl -ne 'print "$1\n" if /"resolution.(\w+)/g' FILE_NAME
perl -ne 'print "$1\n" if m/"resolution.(\w+)/sig' FILE_NAME
I'm expecting to get:
OPEN_IT_COMPLAINTS_FOUND
OPEN_IT_COMPLAINTS_NOT_FOUND
MCS_GET_COMPLAINTS_WARNING
MCS_GET_COMPLAINTS_TIMEOUT
MCS_GET_COMPLAINTS_FAIL
But I'm only getting:
OPEN_IT_COMPLAINTS_FOUND
If I put the above mentioned kind of expressions each in a single line inside the file as this:
\"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\"
I do get the expected output:
OPEN_IT_COMPLAINTS_NOT_FOUND1
OPEN_IT_COMPLAINTS_NOT_FOUND2
OPEN_IT_COMPLAINTS_NOT_FOUND2
OPEN_IT_COMPLAINTS_NOT_FOUND4
Upvotes: 1
Views: 292
Reputation: 373
It's very easy. Just save all the matched in an array @x:
perl -ne 'say join "\n",@x if @x=/\"resolution.(\w+)/g' FILE_NAME
@x will be evaluated (by if
) to be true if it's not empty.
Upvotes: 1
Reputation: 123561
if /.../g
is using the regex in a scalar context. In this context /.../g
is returning only a single match. The next /.../g
will return the next single match etc:
$ 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
If you want all matches you have to either call /.../g
repeatedly in scalar context or use it in array context. The first option would look like this:
$ 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
In array context /.../g
returns all matches at once as an array, i.e.
@matches = /"resolution.(\w+)/
Within some command line statement this could look like this:
$ 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
Upvotes: 2
Reputation: 5972
Scalar vs. list context:
$ 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
i.e. /g
only returns multiple results if the regex gets repeatedly executed. Your command line only executed the match once.
Maybe the following code example makes it more clear;
#!/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;
Upvotes: 1
Reputation: 22294
I don't see OPEN_IT in your input file.
Try looping over the matches instead:
perl -ne 'print "$_\n" for (/"resolution.(\w+)/g)' FILE_NAME
The parenthesis give the match a list context, the for will set $_
to each match one at a time and call print "$_\n"
on each.
Upvotes: 1