LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   awk syntax (http://www.linuxquestions.org/questions/programming-9/awk-syntax-762595/)

wakatana 10-17-2009 11:50 AM

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

tronayne 10-17-2009 04:54 PM

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.

wakatana 10-18-2009 10:52 AM

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.

catkin 10-18-2009 12:34 PM

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 (Post 3722806)
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

wakatana 10-18-2009 05:01 PM

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

tronayne 10-18-2009 06:04 PM

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.

wakatana 10-20-2009 06:35 AM

So in concusion declaring variables should be done in BEGIN block ? Or Am I wrong ?

tronayne 10-20-2009 07:21 AM

Quote:

Originally Posted by wakatana (Post 3725869)
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.

catkin 10-20-2009 11:08 AM

Quote:

Originally Posted by wakatana (Post 3724119)
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.

catkin 10-20-2009 11:15 AM

Quote:

Originally Posted by wakatana (Post 3725869)
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.

pixellany 10-20-2009 02:51 PM

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


All times are GMT -5. The time now is 08:51 AM.