LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-26-2012, 07:02 PM   #1
0.o
Member
 
Registered: May 2004
Location: Raleigh, NC
Distribution: Debian, Solaris, HP-UX, AIX
Posts: 208

Rep: Reputation: 35
Regex Over Multiple Lines -- Perl


I am trying to match the following data over multiple lines:

Code:
Jan 21 22:38:09 MSIDCB01DC HEALTH: HMNOTIFY: Link State Propagation (Sensor MSIABC01EIS): Severity: recovery: s2p2_s2p1 is Normal
s1p2_s1p1 is Normal
Jan 21 22:38:56 MSIDCB01DC HEALTH: HMNOTIFY: Link State Propagation (Sensor MSIABC02EIS): Severity: recovery: s2p1_s2p2 is Normal
s1p2_s1p1 is Normal
I need to pull the name of the sensor out and also the interface states and interface names. I have no issues pulling that info off of the first line, but I am unable to pull it from the second line. I am using perl. Any assistnace would be appreciated.

Thanks!
 
Old 01-27-2012, 10:02 AM   #2
anomie
Senior Member
 
Registered: Nov 2004
Location: Texas
Distribution: RHEL, Scientific Linux, Debian, Fedora
Posts: 3,935
Blog Entries: 5

Rep: Reputation: Disabled
Just trying to understand:
  • You wish to match across multiple lines? (There's a regex modifier - 's' - that can help with this.)
  • Or would it be sufficient to match one line at a time for printing / pushing onto an array?
 
Old 01-27-2012, 10:09 AM   #3
Cedrik
Senior Member
 
Registered: Jul 2004
Distribution: Slackware
Posts: 2,140

Rep: Reputation: 244Reputation: 244Reputation: 244
How do you get the lines ?

Code:
perl -ne 'do {
  /Sensor\s(.*)\).*\s(.*)\sis\s(.*)/;
  print "Sensor: $1\n", "Interface: $2\n", "Status: $3\n";
} if /Sensor/' file
 
Old 01-28-2012, 06:06 PM   #4
0.o
Member
 
Registered: May 2004
Location: Raleigh, NC
Distribution: Debian, Solaris, HP-UX, AIX
Posts: 208

Original Poster
Rep: Reputation: 35
Quote:
Originally Posted by Cedrik View Post
How do you get the lines ?

Code:
perl -ne 'do {
  /Sensor\s(.*)\).*\s(.*)\sis\s(.*)/;
  print "Sensor: $1\n", "Interface: $2\n", "Status: $3\n";
} if /Sensor/' file
I am getting the lines via a syslog message. The script is executed via syslog-ng so I am receiving the message line-by-line.
 
Old 01-28-2012, 06:17 PM   #5
Cedrik
Senior Member
 
Registered: Jul 2004
Distribution: Slackware
Posts: 2,140

Rep: Reputation: 244Reputation: 244Reputation: 244
Could you post your script and show where it should be improved ?
I don't get the issue with multiple lines if you get the message line by line :/
 
Old 01-30-2012, 11:54 AM   #6
0.o
Member
 
Registered: May 2004
Location: Raleigh, NC
Distribution: Debian, Solaris, HP-UX, AIX
Posts: 208

Original Poster
Rep: Reputation: 35
Quote:
Originally Posted by Cedrik View Post
Could you post your script and show where it should be improved ?
I don't get the issue with multiple lines if you get the message line by line :/

Here's the part of the script that is in question. I am receiving these messages line-by-line. So, I can't do a nested if like below because the second line will not match the first if. I need to match across both lines to pull out the Sensor hostname, interface names and also the state of the interface across both lines. I have tried using /n to match the new line and even .* to match the newline and have been unsuccessful.

Code:
#Jan 21 22:38:09 MSIABC01DC HEALTH: HMNOTIFY: Link State Propagation (Sensor MISABC01EIS): Severity: recovery: s2p2_s2p1 is Normal 
#s1p2_s1p1 is Normal
if(/link state propagation \(Sensor (MSI[a-z]{3}[0-9]{2,3}[a-z]*)\).* (s[0-9]p[0-9]_s[0-9]p[0-9]) is (normal|triggered)/smi)
{
        my $hostname=$1;
        my @interface;
        push(@interface,$2);
        push(@interface,$3);
        if(/(^s[0-9]p[0-9]_s[0-9]p[0-9]) is (normal|triggered)/i)
        {
                push(@interface,$1);
                push(@interface,$2);
        }
        print @interface;    
}
 
Old 01-30-2012, 12:08 PM   #7
Cedrik
Senior Member
 
Registered: Jul 2004
Distribution: Slackware
Posts: 2,140

Rep: Reputation: 244Reputation: 244Reputation: 244
Why not use different ifs for each line ?
Code:
#Jan 21 22:38:09 MSIABC01DC HEALTH: HMNOTIFY: Link State Propagation (Sensor MISABC01EIS): Severity: recovery: s2p2_s2p1 is Normal 
#s1p2_s1p1 is Normal

my @interface;

if(/link state propagation \(Sensor (MSI[a-z]{3}[0-9]{2,3}[a-z]*)\).* (s[0-9]p[0-9]_s[0-9]p[0-9]) is (normal|triggered)/smi)
{
        my $hostname=$1;
        
        push(@interface,$2);
        push(@interface,$3);
}
if(/(^s[0-9]p[0-9]_s[0-9]p[0-9]) is (normal|triggered)/i)
{
        push(@interface,$1);
        push(@interface,$2);
}
print @interface;
 
Old 01-30-2012, 12:33 PM   #8
0.o
Member
 
Registered: May 2004
Location: Raleigh, NC
Distribution: Debian, Solaris, HP-UX, AIX
Posts: 208

Original Poster
Rep: Reputation: 35
Quote:
Originally Posted by Cedrik View Post
Why not use different ifs for each line ?
Code:
#Jan 21 22:38:09 MSIABC01DC HEALTH: HMNOTIFY: Link State Propagation (Sensor MISABC01EIS): Severity: recovery: s2p2_s2p1 is Normal 
#s1p2_s1p1 is Normal

my @interface;

if(/link state propagation \(Sensor (MSI[a-z]{3}[0-9]{2,3}[a-z]*)\).* (s[0-9]p[0-9]_s[0-9]p[0-9]) is (normal|triggered)/smi)
{
        my $hostname=$1;
        
        push(@interface,$2);
        push(@interface,$3);
}
if(/(^s[0-9]p[0-9]_s[0-9]p[0-9]) is (normal|triggered)/i)
{
        push(@interface,$1);
        push(@interface,$2);
}
print @interface;
That is a possibility, but it would be much cleaner to use regex to match across both lines.
 
Old 01-30-2012, 12:38 PM   #9
Cedrik
Senior Member
 
Registered: Jul 2004
Distribution: Slackware
Posts: 2,140

Rep: Reputation: 244Reputation: 244Reputation: 244
Why cleaner ? For coding style, personally I prefer separate ifs, but YMMV

Another solution is to store first line in a variable, append the second line, then use multiline matching, but I don't see the point, better to process lines as soon as they arrive imho
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] differences between shell regex and php regex and perl regex and javascript and mysql golden_boy615 Linux - General 2 04-19-2011 01:10 AM
Perl: Multiple line regex matching sammywammy Programming 4 02-09-2011 10:03 AM
Perl to find regex and print following 5 lines after regex casperdaghost Linux - Newbie 3 08-29-2010 08:08 PM
[SOLVED] Perl regex not matching across multiple lines despite ms flags gfarrell Programming 30 08-18-2010 04:10 AM
Searching for 2 empty lines by RegEx in perl mosh Programming 8 09-08-2004 02:51 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:53 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration