7

How do I implement a carriage or newline return in every awk command in a shell script, such that each command's output is separated from the next?

Perhaps I need more specification. I have two awk commands, listed below:

awk {print $1, $2}, awk command 1, outputs:

John Bender
Bohn Jender
Jen Bondher

awk '{print $3, $4}', command 2, outputs:

AGE 21
AGE 420
AGE 2345678909876543234567890876543234567890876543

When combined in a shell script, and run with ./<testscript>.sh <textfile>, the command line obviously outputs:

John Bender
Bohn Jender
Jen Bondher
AGE 21
AGE 420
AGE 2345678909876543234567890876543234567890876543

Because I want the newline append PER awk command, I want the output to look simply like:

John Bender
Bohn Jender
Jen Bondher

AGE 21
AGE 420
AGE 2345678909876543234567890876543234567890876543

Previous attempts at appending "\n" have resulted in:

John Bender

Bohn Jender

Jen Bondher

AGE 21

AGE 420

AGE 2345678909876543234567890876543234567890876543

..which is certainly unwanted.

2 Answers 2

8

As you are running from inside a shell script, just add echo after each awk command i.e. in between the commands you want to get separate outputs. echo adds a newline. For example:

awk '{print $1 $2}' file.txt
echo
awk '{print $3, $4}' file.txt

Original answer:

Append printf "\n" at the end of each awk action {}.

printf "\n" will print a newline.

Example:

% awk '{print $1; printf "\n"}' <<<$'foo bar\nspam egg'
foo

spam

11
  • Thank you, but not quite what I was looking for. I looked to newline different output blocks per awk command rather than newline each command output line itself. If this is unclear, please check edited post above, and if you could be so kind as to edit your answer to fit those circumstances.
    – Anonymous
    Oct 17, 2016 at 5:20
  • @KMoy Check my edits
    – heemayl
    Oct 17, 2016 at 5:25
  • 2
    @heemayl alternative would be to use END block with printf at the end of first statement instead of echo Oct 17, 2016 at 7:50
  • @Serg Definitely that. It seems to me that OP is inclined towards a separate command though.
    – heemayl
    Oct 17, 2016 at 7:51
  • 1
    @Serg still, in the END block many awk's distros will use the last line when using print: seq 10 | awk 'END {print}' returns 10 in GNU awk, for example. This is implementation specific, so it is best not to rely on its behaviour. [BTW please use @ if you were answering me :) ]
    – fedorqui
    Oct 17, 2016 at 9:47
2

Just because it's possible to do so, here's what alternative approaches can be taken.

ARGIND with NR and FNR variables

This approach runs through file twice, and at the moment of running through file second time, it prints a newline, which is achieved via use of a few interesting ideas.

  • For processing same file but extracting different info, file is given on command line twice.

  • How do we distinguish when we're running through first file ( to extract fields $1 and $2 ) and when through second ? Via using ARGIND variable.

  • NR is total record processed so far, and FNR is total record processed in current file. With the first file, they are the same.When will they differ ? When we get to second file. At this moment we need to print newline, but somehow prevent it being printed for other values where NR > FNR. We raise a flag ( via flag variable ).

Sample output:

$ awk '!flag && NR>FNR {print "";flag=1} ARGIND==1{print $1,$2}ARGIND==2{print $3,$4}' data.txt data.txt                  
John Bender
Bohn Jender
Jen Bondher

AGE 21
AGE 420
AGE 2345678909876543234567890876543234567890876543

Use of END clause

As mentioned in comments under heemayls answer, when using two separate awk commands, one can use END block to print something once processing of file is complete

$ awk '{print $1,$2}END{print "\n"}' data.txt;  awk '{print $3,$4}' data.txt                                                          
John Bender
Bohn Jender
Jen Bondher


AGE 21
AGE 420
AGE 2345678909876543234567890876543234567890876543

Variation on END block with associative arrays

Since your $3 block is basically same thing over and over ( string "AGE" ) you don't have to store it, but you can store $4 into associative array. Then in END block you can iterate over stored values after printing newline.

$ awk '{print $1,$2;age[i++]=$4}END{print"";for(var in age) print "AGE",age[var]}' data.txt                                           
John Bender
Bohn Jender
Jen Bondher

AGE 21
AGE 420
AGE 2345678909876543234567890876543234567890876543
3
  • You can also use ENDFILE and the NR==FNR trick to process two files in one: awk 'FNR==NR {print $1, $2; next} {print $3, $4} ENDFILE {print ""}' file{,}.
    – fedorqui
    Oct 18, 2016 at 10:04
  • @fedorqui would you like to post that as an answer ? Oct 18, 2016 at 17:44
  • Not specially, I just like to suggest alternatives. So if you like it, feel free to add it to your answer.
    – fedorqui
    Oct 19, 2016 at 9:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .