Training, Open Source computer languages
PerlPHPPythonMySQLApache / TomcatTclRubyJavaC and C++LinuxCSS 
Search for:
Home Accessibility Courses Diary The Mouth Forum Resources Site Map About Us Contact
 
For 2023 (and 2024 ...) - we are now fully retired from IT training.
We have made many, many friends over 25 years of teaching about Python, Tcl, Perl, PHP, Lua, Java, C and C++ - and MySQL, Linux and Solaris/SunOS too. Our training notes are now very much out of date, but due to upward compatability most of our examples remain operational and even relevant ad you are welcome to make us if them "as seen" and at your own risk.

Lisa and I (Graham) now live in what was our training centre in Melksham - happy to meet with former delegates here - but do check ahead before coming round. We are far from inactive - rather, enjoying the times that we are retired but still healthy enough in mind and body to be active!

I am also active in many other area and still look after a lot of web sites - you can find an index ((here))
RegEx

Posted by matt (matt), 14 March 2003
I am looking for some help with a regular expression. I need to print the line below the one that I have matched. Any ideas?

Matt

Posted by admin (Graham Ellis), 15 March 2003
The answer to this one rather depends on how the data that you're checking is held or being read.

If you're reading data line by line from the file (or other data stream), then set a variable to note where a match occurs or not to any particular read, and print out the current line if that variable holds a true value once you've read in the next line:
Code:
#!/usr/bin/perl

open (FH,"access_log");

while ($line = <FH>) {
       print $line if ($wantnext);
       $wantnext = ($line =~ /^seaweed/);
       }


If you have "slurped" the whole stream of incoming data, you can do it with a counter on a for loop:
Code:
#!/usr/bin/perl

open (FH,"access_log");
@allofit = <FH>;

for ($k=0; $k<@allofit; $k++) {
       print $allofit[$k+1] if ($allofit[$k] =~ /^seaweed/);
       }


And if you have the whole of the incoming string in a single variable you could do it with a regular expression match:

Code:
#!/usr/bin/perl

undef $/;
open (FH,"access_log");
$allofit = <FH>;

while ($allofit =~ /^seaweed.*\n(.*\n)/mg) {
       print $1;
       }


This last one calls for a bit more explanation as it's likely to look pretty odd to many readers.    

The whole of your file of incoming data is placed into a scalar, which is then matched against a regular expression using the "g" modifier.  This means that each time you run the match statement, it resumes in the string at the point at which the match ended, and it returns a false value once there are no more matches - it's really a match with a memory, where match number n depends on where match n-1 left off.

The example uses the ^ operator to indicate "starting with", and the "m" modifier is used to change this so that it will match not only at the very beginning of the string (the default) but also at any embedded new line start.   It also uses the fact that the . character (full stop) matches any character EXCEPT a new line since we have NOT specified the "s" modifier.

Finally, the round brackets around a part of the match indicate that the part selected is an "interesting bit" (a.k.a. a capture string), and whatever matches the bracket is to be stored into $1 if the match succeeds.

Typical Perl - three paragraphs or so to explain a couple of lines of code.  I thrive on it!

A question for you to ask yourself - what do you want to do / print out if you get a match on the very last line of your data?  My examples above simply won't come up with anything to indicate that the final line matched, but you might want to do something different.

All three examples have been tested on a file of web log data that I use for purposes such as this, and have correctly printed out 4 lines from a file of just under 7000 lines - I have been told which hosts came along to the web server immediately after "seaweed":

Code:
sealion - - [15/Jul/2002:08:32:48 -0400] "GET /perl/index.html HTTP/1.0" 200 999
magnet - - [15/Jul/2002:08:38:04 -0400] "GET /perl/interact/wool.html HTTP/1.0" 200 637
flipper - - [15/Jul/2002:12:33:33 -0400] "GET /perl/manual/perl.html HTTP/1.0" 200 14316
seal - - [15/Jul/2002:13:02:45 -0400] "GET /pub/index.html HTTP/1.0" 200 1158





This page is a thread posted to the opentalk forum at www.opentalk.org.uk and archived here for reference. To jump to the archive index please follow this link.

You can Add a comment or ranking to this page

© WELL HOUSE CONSULTANTS LTD., 2024: Well House Manor • 48 Spa Road • Melksham, Wiltshire • United Kingdom • SN12 7NY
PH: 01144 1225 708225 • FAX: 01144 1225 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho