CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Match and Print lines, between 2 patterns spanning mulitiple lines.

 



new2perl2016
Novice

Feb 29, 2016, 10:47 AM

Post #1 of 7 (3718 views)
Match and Print lines, between 2 patterns spanning mulitiple lines. Can't Post

Dear Gurus,

Perl noobs here. Would somebody be able to tell me how to match 2 patterns that are on different lines, we'll actually the line below the first match. My file appears below.

#Feb 19 15:22:21 206021 152221.684878 7219 Session-60 INFO: Updating servercert for user=(billybob) imadesomechanges, updated by billybob
#Feb 19 15:22:21 206021 152221.694424 7220 server.framework.scsf.client Session-60 INFO: MessageFromClient{msgId:UPDATE,state:{lastUpdatedDateTime:1427129443000,id:billybob,key:37581,oldDbKey:41984,type:TakerUser,lastUpdatedBy:billybob,partyId:ARAGORN,permissions:{perms:[,SequesteredTrading],tkrPerms:{perms:[AlternateUpdateXXXFundName,AlternateUpdateXXXscriptions,AlternateIcebergOrder],rfqTradeWarnLimit:0,rfqTradeAbsoluteLimit:0,espTradeAbsoluteLimit:0}}}} sendServer#

if i use say

if (/Updating servercert.*/) {
print "$_";

it will print the first line -

#Feb 19 15:22:21 206021 152221.684878 7219 Session-60 INFO: Updating servercert for user=(billybob) imadesomechanges, updated by billybob

I've tried if (/Updating servercert.*,permissions/) {


but no matter what I've tried in my if statement i can't match the second line. I'd like to match up to ,permissions:

Your feedback would be greatly appreciated.


BillKSmith
Veteran

Feb 29, 2016, 1:44 PM

Post #2 of 7 (3711 views)
Re: [new2perl2016] Match and Print lines, between 2 patterns spanning mulitiple lines. [In reply to] Can't Post

When you are matching multi-line strings, you need the /m and /s modifiers. Without the /s, a "." does not match a newline. Without the /m, "^" and "$" match start and end-of-string, not start and end-of-line.

Assuming that you have slurped the two lines of your file into a single string, this code will demonstrate a match.


Code
use strict; 
use warnings;
use English;

my $regexp = qr/Updating servercert.*permissions/ms;

my $input_file
= 'Feb 19 15:22:21 206021 152221.684878 7219 Session-60 INFO:'
. ' Updating servercert for user=(billybob) imadesomechanges,'
. ' updated by billybob'
. "\n"
. 'Feb 19 15:22:21 206021 152221.694424 7220 server.framework.'
. 'scsf.client Session-60 INFO: MessageFromClient{msgId:UPDATE,'
. 'state:{lastUpdatedDateTime:1427129443000,id:billybob,key:'
. '37581,oldDbKey:41984,type:TakerUser,lastUpdatedBy:billybob,'
. 'partyId:ARAGORN,permissions:{perms:[,SequesteredTrading],'
. 'tkrPerms:{perms:[AlternateUpdateXXXFundName,'
. 'AlternateUpdateXXXscriptions,AlternateIcebergOrder],'
. 'rfqTradeWarnLimit:0,rfqTradeAbsoluteLimit:0,'
. 'espTradeAbsoluteLimit:0}}}} sendServer#'
. "\n"
;

$input_file =~ $regexp;

print $MATCH, "\n";


The output does not display well in this forum, so I have attached it as a file
Good Luck,
Bill
Attachments: new2perl2016.txt (0.33 KB)


Laurent_R
Veteran / Moderator

Mar 1, 2016, 3:21 AM

Post #3 of 7 (3689 views)
Re: [new2perl2016] Match and Print lines, between 2 patterns spanning mulitiple lines. [In reply to] Can't Post

Bill's solution is perfect if you have slurped the whole file into a scalar variable. Assuming you are reading the file line by line, you could use the flip-flop operator to print everything between the first match and the second one:

Code
use strict;  
use warnings;


my $input_file =
'Feb 19 15:22:21 206021 152221.684878 7219 Session-60 INFO:
Updating servercert for user=(billybob) imadesomechanges,
updated by billybob
Feb 19 15:22:21 206021 152221.694424 7220 server.framework.
scsf.client Session-60 INFO: MessageFromClient{msgId:UPDATE,
state:{lastUpdatedDateTime:1427129443000,id:billybob,key:
37581,oldDbKey:41984,type:TakerUser,lastUpdatedBy:billybob,
partyId:ARAGORN,permissions:{perms:[,SequesteredTrading],
tkrPerms:{perms:[AlternateUpdateXXXFundName,
AlternateUpdateXXXscriptions,AlternateIcebergOrder],
rfqTradeWarnLimit:0,rfqTradeAbsoluteLimit:0,
espTradeAbsoluteLimit:0}}}} sendServer#'
;

open my $IN, "<", \$input_file or die "Error: $!"; # simulating a file
while (<$IN>) {
print if /Updating servercert/../permissions/;
}


which gives the following output:

Code
$ perl multiline_match2.pl 
Updating servercert for user=(billybob) imadesomechanges,
updated by billybob
Feb 19 15:22:21 206021 152221.694424 7220 server.framework.
scsf.client Session-60 INFO: MessageFromClient{msgId:UPDATE,
state:{lastUpdatedDateTime:1427129443000,id:billybob,key:
37581,oldDbKey:41984,type:TakerUser,lastUpdatedBy:billybob,
partyId:ARAGORN,permissions:{perms:[,SequesteredTrading],



BillKSmith
Veteran

Mar 1, 2016, 6:34 AM

Post #4 of 7 (3676 views)
Re: [BillKSmith] Match and Print lines, between 2 patterns spanning mulitiple lines. [In reply to] Can't Post

Closer examination of your original post proves that you are reading "line-by-line" ($_ contains only one line). This suggests that Laurent's solution is probably correct.

If you run his code on the original file, it will output both lines exactly as they are in the input. (His example contains extra newlines which are copied into the output.)

I had understood that you wanted to print only the characters matched by your regular expression.
Good Luck,
Bill


new2perl2016
Novice

Mar 1, 2016, 9:20 AM

Post #5 of 7 (3663 views)
Re: [BillKSmith] Match and Print lines, between 2 patterns spanning mulitiple lines. [In reply to] Can't Post

Bill/Laurent,

Thanks very much for your replies. The flip flop operator helped a lot in my output. I was able to extract the information i needed. Now, my only issue is the output is assigned to a $var, which should be printed out in an email alert. The issue i am having is 2 emails get generated :(

1 for the first line and another for the second. Any easy way to handle that scenario?


Laurent_R
Veteran / Moderator

Mar 1, 2016, 12:03 PM

Post #6 of 7 (3656 views)
Re: [new2perl2016] Match and Print lines, between 2 patterns spanning mulitiple lines. [In reply to] Can't Post

Please show your code for sending the e-mails.


new2perl2016
Novice

Mar 1, 2016, 12:19 PM

Post #7 of 7 (3654 views)
Re: [Laurent_R] Match and Print lines, between 2 patterns spanning mulitiple lines. [In reply to] Can't Post


Code
#use strict; 
my $mail_d = 'apples@yahoo.com';

my $logpath = "cat /test/integration123/logs-std/`date +%H`";

open FF, "$logpath |";

while (<FF>) {
#print "LINE = $_";


if ( /Updating servercert/ .. /sendServer/ ) {

#print "$_";
my $line = $_;
# s/\n//g;
#$line =~ s/\n//g;
#print "$line";
chomp ($line);
$line =~ s/systems.*INFO://;
$line =~ s/\) .*updated/), updated/;
$line =~ s/^.*party:/ ,party: /;

$line =~ s/,perms.*$//;
print "$line";

#open ML, "| mutt -e\"set realname='Customer Support Group'; set use_from=yes; set from='supportgroup\@yahoo.com'; set envelope_from=yes\" -s 'TEST Alert! SOMETHING CHANGED' -- $mail_dest";
#print ML "$line";
#close ML;
next;
}

}

close FF;



In Reply To

The output displayed on the screen would be

Mar 1 20:10:03 Updating servercert for user=(xxxxxx), updated by billybob ,party: DEMOACCOUNT123

so if I set this to an email I would get 2 emails, one for

Mar 1 20:10:03 Updating servercert for user=(xxxxxx), updated by billybob

and another for

,party: DEMOACCOUNT123

***

Ideally is there also away grep the file handle to give me say the last minute in a log?

for example the old unix way cat logfile |grep `date "+%R" -d "1 mins ago"`

Many thanks to all.!!
Smile


(This post was edited by FishMonger on Mar 1, 2016, 2:40 PM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives