LinuxQuestions.org
Share your knowledge at the LQ Wiki.
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 10-17-2009, 10:50 AM   #1
wakatana
Member
 
Registered: Jul 2009
Location: Slovakia
Posts: 141

Rep: Reputation: 16
awk syntax


Hi I am trying to understand AWK syntax
so I tried this command which gives me the home directory of root

Code:
awk 'BEGIN { FS = ":"} {if ($1 == "root") print $6 }' /etc/passwd
I would know what are the following commands doing. The first one prints all /etc/passwd, second prints nothing.

Code:
awk 'FS = ":"; {if ($1 == "root") print $6 }' /etc/passwd
Code:
awk '{FS = ":"; if ($1 == "root") print $6 }' /etc/passwd
What are the differences between those three commands? I know about awk that in BEGIN I put code that is executed once before processing rows. and END is executing at the end of processing all rows.


also this command work as expected but it is just different form of first
Code:
awk -F ':' '{if ($1 == "root") print $6 }' /etc/passwd
Thanks a lot
 
Old 10-17-2009, 03:54 PM   #2
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
When you set an AWK variable (FS is a predefined variable and you're resetting it to a new value), you really need to do that in the BEGIN section; that way, it stays in effect throughout the program execution.

Just the way it's done.
 
Old 10-18-2009, 09:52 AM   #3
wakatana
Member
 
Registered: Jul 2009
Location: Slovakia
Posts: 141

Original Poster
Rep: Reputation: 16
And is there ways if is variable declared not in BEGIN ? or it is just my mistake ? i think it is syntacticaly correct because awk did not report syntax error.
 
Old 10-18-2009, 11:34 AM   #4
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Hello wakatana

The awksperts haven't rushed to answer so you'll have to make do with me, more of an awkateur.

Quote:
Originally Posted by wakatana View Post
The first one prints all /etc/passwd, second prints nothing.

Code:
awk 'FS = ":"; {if ($1 == "root") print $6 }' /etc/passwd
Code:
awk '{FS = ":"; if ($1 == "root") print $6 }' /etc/passwd
What are the differences between those three commands?
Awk programs are composed of patterns and actions. Actions are enclosed in braces, { }. If the action is omitted the default action of printing the entire line is assumed.

In
Code:
awk 'FS = ":"; {if ($1 == "root") print $6 }' /etc/passwd
there are two pattern-action pairs separated by the ;. The first pattern, intended as (and effective as) an assignment somehow matches all lines (I cant figure out why) and is not followed by an action so the default action is taken. These variations are instructive
Code:
c:~$ awk 'FS = ":"' /etc/passwd
[prints the whole file]
c:~$ awk 'FS = ":" {print $1}' /etc/passwd
[shows the assignment is effective but not for the first line]
In
Code:
awk '{FS = ":"; if ($1 == "root") print $6 }' /etc/passwd
there is no pattern so the action is taken for every line. The FS assignment is not effective for the first line so $1 is the entire line and the match fails as it does for every subsequent line because the root line is the first line. This variation is instructive
Code:
c:~$ awk '{FS = ":"; if ($1 == "bin") print $6 }' /etc/passwd
 
Old 10-18-2009, 04:01 PM   #5
wakatana
Member
 
Registered: Jul 2009
Location: Slovakia
Posts: 141

Original Poster
Rep: Reputation: 16
Thanks catkin for your reply. It is clearer.
I understand it that way
Code:
awk 'FS = "SOMETHING_WEIRD"; {if ($1 == "root") print $6666 }' /etc/passwd
Always will be printed whole file because I have not action before ';' so it execute default action print. And it never goes to second action (after ';') (I dont know why???)


Code:
awk 'FS = ":" {print $1}' /etc/passwd
sets the separator after proceeding first line because of missing BEGIN keyword (for that reason it would not print first line just the others)



Code:
awk '{FS = ":"; if ($1 == "root") print $6 }' /etc/passwd
awk '{FS = ":"; if ($1 == "bin") print $6 }' /etc/passwd
Is still unclear for me. If i made some mistakes please correct me
 
Old 10-18-2009, 05:04 PM   #6
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
According to Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger The AWK Programming Language (New York: Addison-Wesley Publishing Co., 1988, ISBN 0-201-07981X), the syntactic rules for the command line (p. 187) include
Quote:
awk [-Fs] 'program' optional list of filenames
awk [-Fs] -f progrfile optional list of filenames
that is, an assignment to the FS built-in variable is outside the program.

and p. 23
Quote:
The BEGIN and END patterns do not mathc any input rules do not match any input lines. Rather, the statements in the BEGIN action are executed before awk reads any input; the statements in the END action are executed after all input has been read. BEGIN and END thus provide a way to gain control for initialization and wrap up.
Hope this helps some.
 
Old 10-20-2009, 05:35 AM   #7
wakatana
Member
 
Registered: Jul 2009
Location: Slovakia
Posts: 141

Original Poster
Rep: Reputation: 16
So in concusion declaring variables should be done in BEGIN block ? Or Am I wrong ?
 
Old 10-20-2009, 06:21 AM   #8
tronayne
Senior Member
 
Registered: Oct 2003
Location: Northeastern Michigan, where Carhartt is a Designer Label
Distribution: Slackware 32- & 64-bit Stable
Posts: 3,541

Rep: Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065Reputation: 1065
Quote:
Originally Posted by wakatana View Post
So in concusion declaring variables should be done in BEGIN block ? Or Am I wrong ?
Yes, declaring variables is best done in a BEGIN.

If you intend to do a lot of programming in AWK I'd recommend that you find a copy of the Aho-Kernighan-Weinberger book; there are new and used copies available at Amazon.com (http://www.amazon.com/s/ref=nb_ss?ur...07981x&x=0&y=0). They're the guys that invented it and their book is well-written and full of examples.
 
Old 10-20-2009, 10:08 AM   #9
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by wakatana View Post
I understand it that way
Code:
awk 'FS = "SOMETHING_WEIRD"; {if ($1 == "root") print $6666 }' /etc/passwd
Always will be printed whole file because I have not action before ';' so it execute default action print. And it never goes to second action (after ';') (I dont know why???)
It does go but the second action never does anything. Here's why. The next statement has no pattern so matches everything; its action is always executed. But the action has if ($1 == "root") and $1 is never root. The line for root is parsed before FS was set to ":". When line for root is parsed, FS has its default value, a space. The line has no spaces in it so awk puts the whole line in $1. Thus $1 does not match "root". For all the other lines FS is ":" and so awk parses the line as you intend. $1 is the user name but it is never root so does not match. That is why it is instructive to change "root" to "bin" -- and the bin line is printed.
 
Old 10-20-2009, 10:15 AM   #10
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by wakatana View Post
So in concusion declaring variables should be done in BEGIN block ? Or Am I wrong ?
I would not be so proscriptive but it is usual to initialise variables in either the command line or the BEGIN section -- and it helps make the awk program easy to understand.

If you want awk to parse the line with a particular IFS value the you must set that value before awk parses the line and then that must be in either the command line or the BEGIN section.
 
Old 10-20-2009, 01:51 PM   #11
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Mint
Posts: 17,809

Rep: Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743
Moved: This thread is more suitable in <Programming> and has been moved accordingly to help your thread/question get the exposure it deserves.
 
  


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
[python] syntax Error : invalid syntax Python_user Programming 2 09-06-2009 12:52 PM
awk , I need help for awk, just a display function mcandy General 1 12-15-2008 12:21 PM
shell command using awk fields inside awk one71 Programming 6 06-26-2008 04:11 PM
passing a shell variable into awk - syntax for correct interpretation? johnpaulodonnell Programming 3 06-19-2007 12:13 PM
awk syntax to print particular record of xyz file? johnpaulodonnell Linux - Newbie 4 06-14-2007 07:47 AM

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

All times are GMT -5. The time now is 06:17 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
Open Source Consulting | Domain Registration