Print a list of fields passed as a variable

I have a say a.txt file, and below is its contents:

 bob 1 100 lincoln 2 200 chris 3 300 

The contents of the file are separated by a space.

Using awk, I can access each column. Using the command below to print the 1st and 3rd columns, separated by a comma:

 cat a.txt | awk ' { print $1","$3} ' 

and i was successful.

Now I want to dynamically pass criteria from another shell script. Speaking of criteria, I mean - $1","$3 .

I tried the command below, but that didn't work.

 myvar="$1" awk -va="$myvar" ' { print a } ' a.txt 

but this prints $1 3 times since a.txt has three lines.

How to pass a list of awk fields this way?

+6
source share
3 answers

The problem is that the $ in the variable you passed awk is interpreted literally - it cannot be used to refer to a specific field.

For a single field, you can use something like this:

 awk -v field=1 '{ print $field }' file bob lincoln chris 

For multiple fields this is a little trickier:

 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 punched using printf to print each field, followed by either an OFS output field separator or an ORS output record separator, depending on whether this is the last field or not. To separate the fields with a comma, you can pass -v OFS=, as an option.

+6
source

You will need to pass the 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 
+3
source

An alternative to awk using cut , which already takes field positions through a comma-separated list.

 cols="1,3"; cut -d" " -f"$cols" a.txt 

for comma-separated output channel by tr ' ' ',' or use the option --output-delimiter="," cut.

Please note that this will give you the ability to specify input as a closed or open range, for example 1-3 or 2-

+2
source

All Articles