I have a file say a.txt
and below are the contents of it:
bob 1 100
lincoln 2 200
chris 3 300
The file contents are separated by space.
Using awk, I could access each column. Using below command
to print 1st and 3rd columns separated by comma:
cat a.txt | awk ' { print $1","$3} '
and I was successful.
Now I want to pass the criteria dynamically from another shell script. By saying criteria I mean - $1","$3
.
I tried the below command but it didn't work.
myvar="$1"
awk -v a="$myvar" ' { print a } ' a.txt
but this is printing $1
3 times as there are three rows in a.txt
.
How can I pass a list of fields to awk in this way?
The problem here is that the $
in the variable you have passed to awk is interpreted literally - it cannot be used to refer to a specific field.
For a single field, you could use something like this:
awk -v field=1 '{ print $field }' file
bob
lincoln
chris
For multiple fields, this is a little more complicated:
awk -v fields="1 3" 'BEGIN{ n = split(fields,f) }
{ for (i=1; i<=n; ++i) printf "%s%s", $f[i], (i<n?OFS:ORS) }' file
bob 100
lincoln 200
chris 300
The list of fields is passed as a string, which is split into an array. The array is then looped through, using printf
to output each field, followed by either the Output Field Separator OFS
or the Output Record Separator ORS
, depending on whether it's the last field or not.
To separate the fields with a comma, you can pass -v OFS=,
as an option.
You will need to pass a delimited string to awk
and inside awk
use split
to split on that delimiter.
Something like this should work:
awk -v search='1,3' 'BEGIN{split(search, a, ",")}
{f=""; for (i=1;i in a;i++) {printf "%s%s", f, $a[i]; f=OFS} print ""}' file
Output:
bob 100
lincoln 200
chris 300
Alternative to awk solution using cut
which already accepts field positions via comma separated list.
cols="1,3"; cut -d" " -f"$cols" a.txt
for comma separated output pipe to tr ' ' ','
or use --output-delimiter=","
cut option.
Note that this will give you the flexibility to specify input as closed or open range such as 1-3
or 2-