LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices



Reply
 
Search this Thread
Old 10-24-2011, 12:40 PM   #1
protocol
LQ Newbie
 
Registered: May 2005
Posts: 17

Rep: Reputation: 0
Awk - How to print match instead of whole line


I wish to use awk in order to extract email addresses from a log file. I wrote the proper regular expression, however it prints the whole line, while i want it to only print the match (in my case, the email address). Can it be done?

Here is my code:

tail -f /var/log/mail.log | awk '/\ to=([^@]+@[^,:]+)/ { print $7 }'

... where $7 is useless for my goal, it only serves as something to print during testing.

Please assist.

Panos

Last edited by protocol; 10-24-2011 at 01:41 PM.
 
Old 10-24-2011, 12:58 PM   #2
crts
Senior Member
 
Registered: Jan 2010
Posts: 1,604

Rep: Reputation: 446Reputation: 446Reputation: 446Reputation: 446Reputation: 446
Hi,

please provide some sample data. It is hard to guess what is wrong without seeing the input and output.
 
Old 10-24-2011, 01:25 PM   #3
protocol
LQ Newbie
 
Registered: May 2005
Posts: 17

Original Poster
Rep: Reputation: 0
Of course.

A standard line from my mail server's log looks like this:

Code:
Oct 24 19:20:27 server postfix/pipe[31099]: 236041EA4AC0: to=<g.pavlakis@domain.com>, relay=dovecot, delay=0.81, delays=0.8/0/0/0.01, dsn=2.0.0, status=sent (delivered via dovecot service)
I wish to extract the :

Code:
g.pavlakis@domain.com
however, the awk line i posted will print the seventh segment of the line (which sometimes indeed contains the mail address, but sometimes it does not - for example, postfix might add a couple more segments to the line, making the seventh segment irrelevant). So, what i really need, is for postfix to print what it actually matches, not the nth segment or the complete line that contains the match.
 
Old 10-24-2011, 02:03 PM   #4
crts
Senior Member
 
Registered: Jan 2010
Posts: 1,604

Rep: Reputation: 446Reputation: 446Reputation: 446Reputation: 446Reputation: 446
Well, you can surely do this with awk. However, how about a sed solution? It is a bit easier in this case since it is RegEx oriented while awk is field oriented. This worked with your sample:
Code:
sed -r 's/.*to=<([^>]*)>.*/\1/'
This assumes that the address will be inside to=<user@domain>. Also, I notice that you are posting from a Mac in your profile column on the left. If you want to do this on a Mac then we will have to change the sed a bit since the above solution requires GNU sed and as far as I know it is not available by default on a Mac.
 
Old 10-24-2011, 02:07 PM   #5
protocol
LQ Newbie
 
Registered: May 2005
Posts: 17

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by crts View Post
Well, you can surely do this with awk. However, how about a sed solution? It is a bit easier in Also, I notice that you are posting from a Mac in your profile column on the left. If you want to do this on a Mac then we will have to change the sed a bit since the above solution requires GNU sed and as far as I know it is not available by default on a Mac.
Thanks for noticing: it is something i work on a Linux machine i have at the office (i am connected to it via SSH). So it is not for the Mac.

Will your sed solution allow me to assign the found/matched email address to some variable and call an external script for further processing? I mean, after i find the address, i was thinking that perhaps i could "post" it to some other script for e.g. inserting it in a database or something. Is that possible?
 
Old 10-24-2011, 02:14 PM   #6
crts
Senior Member
 
Registered: Jan 2010
Posts: 1,604

Rep: Reputation: 446Reputation: 446Reputation: 446Reputation: 446Reputation: 446
Quote:
Originally Posted by protocol View Post
Will your sed solution allow me to assign the found/matched email address to some variable and call an external script for further processing? I mean, after i find the address, i was thinking that perhaps i could "post" it to some other script for e.g. inserting it in a database or something. Is that possible?
Sure. Just call it like
Code:
variable=$(sed -r 's/.*to=<([^>]*)>.*/\1/' filename)
Notice, that there mustn't be any space between variable and the command substitution $().
 
Old 10-24-2011, 02:20 PM   #7
protocol
LQ Newbie
 
Registered: May 2005
Posts: 17

Original Poster
Rep: Reputation: 0
Lovely.

One thing though.. i run your see code, along with my tail -f (contained in the original one-liner i posted) and it behaves as follows:

a) The first time it matches.. yes it prints the email address alone.
b) All subsequent times it matches, it prints the complete log line that contains the match, exactly as my faulty awk was doing.

Did i miss something? The whole point is that it keeps extracting email addresses as they appear in the log files, in real time.

Panos
 
Old 10-24-2011, 02:26 PM   #8
crts
Senior Member
 
Registered: Jan 2010
Posts: 1,604

Rep: Reputation: 446Reputation: 446Reputation: 446Reputation: 446Reputation: 446
Quote:
Originally Posted by protocol View Post
Lovely.

One thing though.. i run your see code, along with my tail -f (contained in the original one-liner i posted) and it behaves as follows:

a) The first time it matches.. yes it prints the email address alone.
b) All subsequent times it matches, it prints the complete log line that contains the match, exactly as my faulty awk was doing.

Did i miss something? The whole point is that it keeps extracting email addresses as they appear in the log files, in real time.

Panos
Nope, you did not miss anything. By default, sed prints the entire line. A small modification will correct this:
Code:
variable=$(sed -nr 's/.*to=<([^>]*)>.*/\1/p' filename)
The -n option tells sed to not print anything unless specifically instructed to. The 'p' flag at the end of 's///' does exactly that. It only prints when the 's///' command makes a substitution.
 
Old 10-24-2011, 02:30 PM   #9
protocol
LQ Newbie
 
Registered: May 2005
Posts: 17

Original Poster
Rep: Reputation: 0
Sincere thanks.
Problem SOLVED.
 
  


Reply

Tags
awk


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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 On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] AWK print line only if next line matches a string wolverene13 Linux - Newbie 8 10-03-2011 04:32 PM
Awk question (How to print a line other than the first or the last line) maxxum600si Programming 5 10-15-2009 12:48 PM
Sed/Awk: print lines between n'th and (n+1)'th match of "foo" xaverius Programming 17 08-20-2007 12:39 PM
grep/sed/awk - find match, then match on next line gctaylor1 Programming 3 07-11-2007 09:55 AM
compare two files in C and print the line when they do not match calorie712 Programming 7 04-13-2006 02:56 AM


All times are GMT -5. The time now is 02:39 AM.

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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration