在AWK中打印数组中的所有元素

3
我想在awk中循环遍历数组中的所有元素并打印出来。这些值来源于以下文件:
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

我尝试过这个:
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

输出始终为Cys C 27,当我将codes[$1]=$2替换为codes[$2]=$1时,我得到M Met 27

如何让我的代码按顺序打印出所有值?我不明白为什么我的代码会有选择地仅打印一个元素,而我可以告诉数组长度应该是27。(为了使我的代码最小化,我已经省略了else{next}内的代码 - 否则,我只想保留数组codes中的所有元素,并保留else{***}命令)

根据如何查看awk数组中的所有内容?,上面的语法应该可行。我在这里尝试了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)}',并且运行良好。


你最初的问题中只传递了一个文件给awk,后来改成了两个文件。现在我可以看到你正在将两个文件传递给awk程序。请问你是否只想从一个文件中打印数组项?如果是这种情况,那么我们不需要使用第二个文件。 - RavinderSingh13
你的编辑未能解释第二个文件包含了什么。无论如何,你的代码完全忽略了第二个文件。 - tripleee
我想使用第一个输入文件 $input1 来构建一个 awk 数组。然后,我将在文件2中使用该数组来 gsub 一个字段。gsub(key, codes[key], $3)。我的问题是数组 codes,它似乎不让我循环遍历其所有的27个元素。如果需要,我可以提供第二个文件/所有 AWK 代码的链接。 - Kibet
此外,您的代码根本不执行所说的操作。请进行编辑以提供一个[最小可重现示例]。 - tripleee
你的代码假定列之间是用制表符分隔的,但是你的示例数据似乎在列之间使用了空格。如果你真的想处理以空格分隔的数据,请删除 FS="\t"。即使这样,你的代码仍然只能处理两列,而你的数据有三列。 - tripleee
这是一个以制表符分隔的文本文件。我使用FS="\t"的原因是... - Kibet
3个回答

7

根据你所展示的样例和尝试,请尝试以下方法,这些方法是在GNU awk中编写和测试的。

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

稍后我会补充详细说明和原帖遗漏的内容。

说明:对以上内容进行详细说明。

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.

进行了一些编辑。理想情况下,将提供两个输入文件。在 FNR==NR 时读取第一个文件的那部分失败了。 - Kibet
1
@Kibet,是的,我已经在你的问题下面发表了评论,请提供相关信息,这样我就可以尝试帮助你解决问题,谢谢。 - RavinderSingh13
已解决...只是一个 ; 和空格的问题。 - Kibet
@Kibet,很高兴听到这个消息,你能否在这里发布你的答案,这对未来的用户会很有帮助,请务必添加答案,谢谢。 - RavinderSingh13
解决方案 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 - Kibet
1
@Kibet,好的,请将其添加为答案,以便未来用户受益。 - RavinderSingh13

3

我有点困惑你需要什么,但是为了按顺序打印代码,带有编号(忽略名称),您可以执行以下操作:

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

该程序使用两个数组来协调序列号与seq数组中的单个字母,然后将字母与codes数组中的代码对应。

示例用法/输出:

$ 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

1

已解决:错误是由于在此处引入了;造成的:END{for (key in codes);{print key,codes[key],length(codes)}}。 解决方案:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接