I have an assignment running a series of (n)awk commands in one script file. The key of this script file is to filter out certain lines and records of this original text file here, called students:

Frank       Smith       Engineering  Senior     C
John        Doe         Marketing    Junior     B
Nancy       Jones       Engineering  Junior     A
Betty       Anderson    Nursing      Sophomore  B   
Bob         Johnson     History      Freshman   B   
James       Smith       Economics    Senior     A

I have these awk commands in my script file testscript.script.

{print $2, $1, $3, $4, $5}

/A$/ {print $1, $2} 

/!A$/ {print $1, $2}

As of now, when I run nawk -f testscript.script students

For the first few lines of the output I get:

Smith Frank Engineering Senior C
Doe John Marketing Junior B
Jones Nancy Engineering Junior A
Nancy Jones 
Anderson Betty Nursing Sophomore B
Johnson Bob History Freshman B
Smith James Economics Senior A
James Smith

Where as you can see the second command has infused with the first, rather than being separated as desired.

Which leads to my question: How can I separate commands in a shell script, such that each new command has a separate, independent output from others?

  • What output do you want, exactly? – muru Oct 17 '16 at 3:51
  • @muru The first command in the file should output ALL lines in the students text file, but just fields one and two switched. The second command should just print names only of people with A grades. I need these two awk cmd's outputs to be separated (as well as all other commands) – KMoy Oct 17 '16 at 3:53

You might be better off writing a shell script (say foo.sh) with three awk commands instead of a single awk script with three blocks:


awk '{print $2, $1, $3, $4, $5}' "$1"
awk '/A$/ {print $1, $2}' "$1"
awk '/!A$/ {print $1, $2}' "$1"

Then the following should give the desired result:

sh foo.sh students

(You can also do chmod +x foo.sh and then run ./foo.sh students.)


It is working perfectly, and expectedly.

Your command can be rewritten simply as:

awk '{print $2, $1, $3, $4, $5}; /A$/ {print $1, $2}; /!A$/ {print $1, $2}' students

it is composed of 3 awk expressions:

  1. {print $2, $1, $3, $4, $5}

  2. /A$/ {print $1, $2}

  3. /!A$/ {print $1, $2}

All 3 expressions will be applied to all records.

  • The first one is rearranging the fields accordingly

  • The second one is matching if a record ends in A (/A$/), if so the first and second fields are printed

  • The third one is matching if a record ends in !A, if so the first and second ones are printed

  • As the first two records do not satisfy condition of expression 2, the fields are printed according to expression 1. Same goes for record number 4, and 5

  • Only record 3 and 6 match condition of 2nd expression i.e. ends in A so the action of this condition i.e. to print the first two fields in being done right after executing expression 1 i.e. to print rearranged fields. So two actions are being applied for record 3 and 6. I think this is what tripped you up.

  • None of the records match condition of expression 3 i.e. ends in !A, perhaps you meant to use the condition as !/A$/ i.e. records that does not end in A (and apply the desired action).

  • Thank you! However, is using semicolons and a single lengthy line of code the only way to separate these commands? Or is there a way where I can separate the commands in the code (with each command in a new line) as well? I ask this because there are a great many commands I'll have to input to the shell script file, and I'd rather not combine them together in this way. – KMoy Oct 17 '16 at 4:04
  • @KMoy Note that, the ;s are not strictly necessary, it is for readability. Also if you have many such expressions, use the way you are using i.e. use a awk script. My answer is to clear up your confusions. – heemayl Oct 17 '16 at 4:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.