Print a list of fields passed as a variable

2019-06-20 00:35发布

问题:

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?

回答1:

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.



回答2:

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


回答3:

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-



标签: bash shell awk