29

What is the perl regex to print the matched value? For eg I want to print 195 from this string

"2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195".

How can I do that? Thanks in advance

bvr
  • 9,687
  • 22
  • 28
CrazyCoder
  • 2,465
  • 8
  • 36
  • 57

8 Answers8

45

You can use parentheses in regex to capture substrings. The captured groups are stored in $1, $2, and so on. Example:

while (<>) {
    if (/Total Successful Transactions = (\d+)/) {
        print "$1\n";
    }
}

or, somewhat shorter:

while (<>) {
    print "$1\n" if /Total Successful Transactions = (\d+)/;
}

You can also make use of the fact that the match operator (//) in list context returns a list of what was matched by groups:

$\ = '\n'; # Output newline after each print.
while (<>) {
    print for /Total Successful Transactions = (\d+)/;
}

Which lets you write a compact one-liner (the -l option automatically adds newlines to each print, among other things):

perl -lne 'print for /Total Successful Transactions = (\d+)/'
markusk
  • 6,477
  • 34
  • 39
15

Just wanted to reframe the previous answers a bit differently; note that in this case:

$ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /Xy = 3/;'
1 

... we get 1 being printed out - as in "yes, I got a match". If we want to return the matched text portion, as @markusk pointed out, "use parentheses in regex to capture substrings":

$ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = 3)/;'
Xy = 3

However, note that you may have a problem concatenating strings with this idiom, when capturing:

$ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /Xy = 3/ . "\n";' 
1 # OK
$ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = 3)/ . "\n";' 
1 # NOT OK

... so probably better to keep things separate in that case:

$ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = 3)/ ; print "\n";'
Xy = 3 # OK again

 

However, if we want to capture "something", say a digit - then, since we use parentheses, we automatically return just that match with this idiom (not the entire "searched for" string):

$ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /Xy = (\d)/ ; \
print "\n";'
3

... thus, to capture the searched string in its entirety, we should wrap it again in parentheses:

$ perl -e '$str="the variable Xy = 3 in this case"; print $str =~ /(Xy = (\d))/ ; \
print "\n";'
Xy = 33

.... but, we don't get what we expect, because now there are two matches, $1 and $2; and apparently the idiom "print $str =~ /.../" outputs all matches (in this case, "$1$2").

So to get just the searched string in this nested matches case, we now have to explicitly specify only $1:

$ perl -e '$str="the variable Xy = 3 in this case"; $str =~ /(Xy = (\d))/ ; \
print "$1 \n";'
Xy = 3 

EDIT oct 2013: Via Assign one of multiple regex matches to variable as Perl one-liner (dereference array?) - also this can be done for a one liner:

$ perl -e '$str="the variable Xy = 3 in this case"; \
print ( ( $str =~ /(Xy = (\d))/ )[1] ); print "\n";'
3

... however, note the need for a second enveloping set of parentheses for the print to work directly with the regex returned (anonymous?) array.

 

Finally, in a multiline context, make sure to first "slurp" the entire file/text into a single string; then use the /s (single line mode = newline is matched) and /g (global/multiple matches) - and finally, make sure the match expression is in a while loop, so as to iterate through all the matches:

$ echo "some data
IN
123
OUT
some more data
 is about to follow:
IN
256
OUT
done with data
out" | perl -e '$str = do { local $/; <> }; while ($str =~ /(IN(.*?)OUT)/sg) { print "$1\n"} '

IN
123
OUT
IN
256
OUT

Well, hope this helps someone,
Cheers!

Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278
  • Slurping the entire file can be expensive for large inputs. An alternative is to use the range operator: `perl -ne 'print if /IN/../OUT/'` – markusk Jan 11 '18 at 12:20
10

How about just:

print $string =~ /Total Successful Transactions = (\d+)/;

You rarely actually need to use $1 and friends.

ysth
  • 96,171
  • 6
  • 121
  • 214
5
/(\d+$)/;
print $1;

I guess you just want the number 195. Right?

Bruce
  • 7,094
  • 1
  • 25
  • 42
Parikshit
  • 51
  • 1
  • 1
4

The command line version of the accepted answer by @markusk is quite compact:

perl -ne '/Total Successful Transactions = (\d+)/ && print "$1\n";'
mkHun
  • 5,891
  • 8
  • 38
  • 85
Uri Cohen
  • 3,488
  • 1
  • 29
  • 46
2
my $str = '"2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195".';

$str =~ /Total Successful Transactions = (\d+)/;
print $1; 

195 will be stored in $1

Shalini
  • 455
  • 1
  • 3
  • 5
2

Check for digits at the last just before " and ..

#!/usr/bin/env perl

use strict;
use warnings;

my $string = q{"2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195".};
my ($number) = $string =~ m{ (\d+) " \. \z}x;

print "Matched number: $number\n" if defined $number;
Alan Haggai Alavi
  • 72,802
  • 19
  • 102
  • 127
  • Should check if match failed (setting $number to undef). Also, you say "at the last" but don't implement that. – ysth Apr 11 '11 at 16:55
  • _[daxim](http://stackoverflow.com/users/46395/daxim)_: Thank you. _[ysth](http://stackoverflow.com/users/17389/ysth)_: Thank you for letting me know. It was a miss. I have edited my answer. – Alan Haggai Alavi Apr 11 '11 at 18:10
0

Like so:

if ("2011-04-11 00:39:28,736::[main]::INFO (Main.java:73) Test.Main::main() Total Successful Transactions = 195" =~ /(\d+)$/) {
    print $1;
}

Once you match, the matched groups become available as $1..$n.

Sajid
  • 4,381
  • 20
  • 14
  • Thank you but is it possible to say print the value(number) where "Successful Tranaction" is present in the string. – CrazyCoder Apr 11 '11 at 06:10