There’s a file to be processed, columns are separated by tabs:
$ cat system.log
2 camila create db
3 andrew create table
5 greg update table
6 nataly update view
7 greg delete table
9 camila update table
11 nataly create view
12 peter link table
14 andrew update view
15 greg update db
I wanted these lines displayed in a form:
Entry No. 7: camila (action: create db)
To do so, I created the following bash script:
#!/bin/bash
filename=$1
while read line; do
printf $line | awk -F '\t' '{ print "Entry No. ", $1, ": ", $2, " (action: ", $3, ")" }'
done < $filename
However, what I get is:
$ ./log_parser.sh system.log
Entry No. 2 : (action: )
Entry No. 3 : (action: )
Entry No. 5 : (action: )
Entry No. 6 : (action: )
Entry No. 7 : (action: )
Entry No. 9 : (action: )
Entry No. 11 : (action: )
Entry No. 12 : (action: )
Entry No. 14 : (action: )
Entry No. 15 : (action: )
Why only the first column gets processed and what to do to have the whole line processed?
>Solution :
You must quote your variables to prevent word splitting. Consider if $line evaluates to the string 2 camila create db. In that case, printf $line is equivalent to printf 2 camila create db which calls printf with 4 arguments. printf correctly parses those arguments and dutifully writes the string 2. If you want to pass a single argument to printf, you could do printf "$line". But that is also incorrect, as the first argument to printf should be a format string, and you don’t want to use input strings as format strings. Instead, you should write printf '%s' "$line". But don’t do that, either. while read; printf | awk is an anti-pattern. Just use awk to read the input.