By Jay Fougere
Expert Author
Article Date: 2009-08-18
One of the beautiful uses of Perl is to do quick and dirty string manipulations on the command line. In a Unix environment this is especially nice as the output of one command can be piped into Perl for manipulation.
For instance, let's say that I want to view only a couple of specific fields in a log file in realtime, I can tail the log file and pipe it through a small Perl program written on the command line. As an example, let's say I want to view permanent mail delivery errors due to an invalid recipient address in a standard Postfix maillog. I could simply run:
#tail -f /var/log/maillog |grep 550 | grep -v reject:
<snip>
Aug 18 13:54:14 mx1 postfix/smtp[3962]: B5B051137AE: to=
<lesubmissionsnn@example.com>, relay=1.2.3.4[1.2.3.4]:25, delay=0.27, delays=0/0/0.2/0.06, dsn=5.0.0, status=undeliverable (host 1.2.3.4[1.2.3.4] said: 550
<lesubmissionsnn@example.com>: Recipient address rejected: User unknown in local recipient table (in reply to RCPT TO command))
</snip>
And I would recieve some long and ugly lines that tell me more information than what I really need. Now, let's say I just want to see the addresses that are failing. I could run the same command and then pipe it through perl to grab the fields I am interested in. The '-e' flag for perl means "execute".
#tail -f /var/log/maillog |grep 550| grep -v reject: | perl -e 'while(<>){@temp=split(/\s+/,$_); print $temp[6]."\n";}'
And I will recieve a list of the rejected email addresses.
Another favorite of mine is to strip comments from configuration files.
#cat config | perl -e 'while(<>){unless(($_=~m/^#/) or ($_=~m/^\s+#/) or ($_=~m/^\s+$/)){print $_}}'
As you are probably aware, $_ is the current line going through the program. The three regular expressions are fairly simple. The unless statement says that if $_ begins with '#' or if $_ begins with one or more spaces followed immediately by a '#' or if $_ matches only one or more spaces, ignore the line. Otherwise we print it to standard out. You could also redirect this output to a new file name for later use.
#cat config | perl -e 'while(<>){unless(($_=~m/^#/) or ($_=~m/^\s+#/) or ($_=~m/^\s+$/)){print $_}}' > newfile