Print all elements in an array in AWK

Viewed 2208

I want to loop through all elements in an array in awk and print. The values are sourced from the file below:

Ala     A       Alanine
Arg     R       Arginine
Asn     N       Asparagine
Asp     D       Aspartic acid
Cys     C       Cysteine
Gln     Q       Glutamine
Glu     E       Glutamic acid
Gly     G       Glycine
His     H       Histidine
Ile     I       Isoleucine
Leu     L       Leucine
Lys     K       Lysine
Met     M       Methionine
Phe     F       Phenylalanine
Pro     P       Proline
Pyl     O       Pyrrolysine
Ser     S       Serine
Sec     U       Selenocysteine
Thr     T       Threonine
Trp     W       Tryptophan
Tyr     Y       Tyrosine
Val     V       Valine
Asx     B       Aspartic acid or Asparagine
Glx     Z       Glutamic acid or Glutamine
Xaa     X       Any amino acid
Xle     J       Leucine or Isoleucine
TERM    TERM    termination codon

I have tried this:

awk 'BEGIN{FS="\t";OFS="\t"}{if (FNR==NR) {codes[$1]=$2;} else{next}}END{for (key in codes);{print key,codes[key],length(codes)}}' $input1 $input2

And the output is always Cys C 27 and when I replace codes[$1]=$2 for codes[$2]=$1 I get M Met 27.

How can I make my code print out all the values sequentially? I don't understand why my code selectively prints out just one element when I can tell the array length is 27 as expected. (To keep my code minimal I have excluded code within else{next} - Otherwise I just want to print all elements from array codes while retaining the else{***} command)

According to How to view all the content in an awk array?, The syntax above should work. I tried it here echo -e "1 2\n3 4\n5 6" | awk '{my_dict[$1] = $2};END {for(key in my_dict) print key " : " my_dict[key],": "length(my_dict)}' and that worked well.

3 Answers

With your shown samples and attempts please try following, written and tested in GNU awk.

awk '
BEGIN{
  FS=OFS="\t"
}
{
  codes[$1]=$2
}
END{
  for(key in codes){
     print key,codes[key],length(codes)
  }
}' Input_file

Will add detailed explanation and OP's misses too in few mins.

Explanation: Adding detailed explanation for above.

awk '                     ##Starting awk program from here.
BEGIN{                    ##Starting BEGIN section from here.
  FS=OFS="\t"             ##Setting FS and OFS as TAB here.
}
{
  codes[$1]=$2            ##Creating array codes with index of 1st field and value of 2nd field
}
END{                      ##Starting END block of this program from here.
  for(key in codes){      ##Traversing through codes array here.
     print key,codes[key],length(codes)  ##Printing index and value of current item along with total length of codes.
  }
}' Input_file             ##Mentioning Input_file name here.

I'm a bit confused what you are after, but to print the codes sequentially, with the no., (ignoring the name), you can do:

awk '{seq[++n]=$2; codes[$2]=$1} 
    END{for (i=1;i<=n;i++) printf "%s\t%s\t%d\n", codes[seq[i]], seq[i], i}' file

Which uses two arrays to coordinate the sequence number with the single letter in the seq array and then the letter to the code in the codes array.

Example Use/Output

$ awk '{seq[++n]=$2; codes[$2]=$1} 
    END{for (i=1;i<=n;i++) printf "%s\t%s\t%d\n", codes[seq[i]], seq[i], i}' file
Ala     A       1
Arg     R       2
Asn     N       3
Asp     D       4
Cys     C       5
Gln     Q       6
Glu     E       7
Gly     G       8
His     H       9
Ile     I       10
Leu     L       11
Lys     K       12
Met     M       13
Phe     F       14
Pro     P       15
Pyl     O       16
Ser     S       17
Sec     U       18
Thr     T       19
Trp     W       20
Tyr     Y       21
Val     V       22
Asx     B       23
Glx     Z       24
Xaa     X       25
Xle     J       26
TERM    TERM    27

Resolved: The error was brought about by the introduction of ; here: END{for (key in codes);{print key,codes[key],length(codes)}}. Solution:

awk 'BEGIN{FS="\t";OFS="\t"}{if (FNR==NR) {codes[$1]=$2;} else{next}}END{for (key in codes){print key,codes[key],length(codes)}}' $input1 $input2
Related