0

I have a sample flat file which contains the following block

test my array which array is better array huh got it?

INDIA USA SA NZ AUS ARG ARM ARZ GER BRA SPN

I also have an array(ksh_arr2) which was defined like this

ksh_arr2=$(awk '{if(NR==1){for(i=1;i<=NF;i++){if($i~/^arr/){print i}}}}' testUnix.txt)

and contains the following integers

3 5 8

Now I want to parse only those column values which are at the respective numbered positions i.e. third fifth and eighth. I also want the outputs from the 2nd line on wards. So I tried the following

awk '{for(i=1;i<=NF;i++){if(NR >=1 && i=${ksh_arr2[i]}) do print$i ; done}}' testUnix.txt 

but it is apparently not printing the desired outputs. What am I missing ? Please help.

5
  • First: in the IF clause you are assigning a value to the i variable. Commented Nov 19, 2014 at 8:25
  • I am comparing with the array index value .. right ?? Commented Nov 19, 2014 at 8:27
  • Second: where have you defined the ksh_arr2 array? Commented Nov 19, 2014 at 8:28
  • No. The comparison operator and the asigning operator are different in awk. Read this link Commented Nov 19, 2014 at 8:33
  • Any shell array is unknown for awk programs. You have to use -v option, as Jidder and John1024 have used in their solutions. Commented Nov 19, 2014 at 8:35

3 Answers 3

2

How i would approach it

awk -vA="${ksh_arr2[*]}" 'BEGIN{split(A,B," ")}{for(i in B)print $B[i]}' file

Explanation

 -vA="${ksh_arr2[*]}"     -    Set variable A to expanded ksh array

  'BEGIN{split(A,B," ")   -    Splits the expanded array on spaces
                               (effictively recreating it in awk)

  {for(i in B)print $B[i]} -  Index in the new array print the field that is the number 
                              contained in that index

Edit

If you want to preserve the order of the fields when printing then this would be better

awk -vA="${ksh_arr2[*]}" 'BEGIN{split(A,B," ")}{while(++i<=length(B))print $B[i]}' file
Sign up to request clarification or add additional context in comments.

11 Comments

I think you may have meant * rather than @: When I tested it, A="${ksh_arr2[@]}" expanded out to several strings and did not assign properly.
@John1024 Oh yeah, didn't realise that would be an issue. Thanks :)
@John1024 Also i realise that the fact that my answer(and EDIT) were posted after yours and may look like i just copied your answer as they look very similar, i would just like to point out that this is not the case and i was in the process of creating(and Editing) whilst you posted yours. Great minds think alike :)
Yes, that can happen. Regards
@Jidder I tried ..awk -vK="${ksh_arr2[*]}" 'BEGIN{split(K,b," ");}{for(i in b)print $b[i]}' testUnix.txt , now it says awk: String 3 cannot contain a newline character. Please explain.
|
1

Since no sample output is shown, I don't know if this output is what you want. It is the output one gets from the code provided with the minimal changes required to get it to run:

$ awk -v k='3 5 8' 'BEGIN{split(k,a," ");} {for(i=1;i<=length(a);i++){print $a[i]}}' testUnix.txt 
array
array
array



SA
AUS
ARZ

The above code prints out the selected columns in the same order supplied by the variable k.

Notes

  • The awk code never defined ksh_arr2. I presume that the value of this array was to be passed in from the shell. It is done here using the -v option to set the variable k to the value of ksh_arr2.

  • It is not possible to pass into awk an array directly. It is possible to pass in a string, as above, and then convert it to an array using the split function. Above the string k is converted to the awk array a.

  • awk syntax is different from shell syntax. For instance, awk does not use do or done.

Details

  • -v k='3 5 8'

    This defines an awk variable k. To do this programmatically, replace 3 5 8 with a string or array from the shell.

  • BEGIN{split(k,a," ");}

    This converts the space-separated values in variable k into an array named a.

  • for(i=1;i<=length(a);i++){print $a[i]}

    This prints out each column in array a in order.

Alternate Output

If you want to keep the output from each line on a single line:

$ awk -v k='3 5 8' 'BEGIN{split(k,a," ");} {for(i=1;i<length(a);i++) printf "%s ",$a[i]; print $a[length(a)]}' testUnix.txt 
array array array

SA AUS ARZ

3 Comments

You would want to print $a[i] not i as that will just be 1-N
This does not print the values which are at 3rd 5th and 8th column :(
@Jidder Thanks. Answer updated: this should fix the column issue.
0

awk 'NR>=1 { print $3 " " $5 " " $8 }' testUnix.txt

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.