首页 > 解决方案 > AWK 通过在特定列上拆分字符串以匹配 bash 中的另一个数组来对数组进行排序

问题描述

a我有一个包含以下几行的数组

rs6605071   chr1:962943 C   ENSG00000188976 ENST00000487214
rs6605071   chr1:962943 C   ENSG00000187961 ENST00000622660
rs6605071   chr1:962943 C   84069   NM_001160184.1
rs6605071   chr1:962943 C   339451  NC_006462594.2
rs6605071   chr1:962943 C   339451  XR_001737138.1
rs6605071   chr1:962943 C   339451  XM_006710600.3

和另一个具有以下行的有序数组b

NC
NG
NM
NP
NR
XM
XP
XR
WP

我想对数组中的行进行排序a以匹配第b5 列上数组的顺序以获得所需的输出:

rs6605071   chr1:962943 C   339451  NC_006462594.2
rs6605071   chr1:962943 C   84069   NM_001160184.1
rs6605071   chr1:962943 C   339451  XM_006710600.3
rs6605071   chr1:962943 C   339451  XR_001737138.1
rs6605071   chr1:962943 C   ENSG00000188976 ENST00000487214
rs6605071   chr1:962943 C   ENSG00000187961 ENST00000622660

我尝试通过在第 5 列上拆分来执行以下命令,但它正在打印空行:

awk -F '\t' -v OFS='\t' 'FNR==NR{split(a[$5],t,"_"); t[1]=$0;next}
{print a[$1]}' <(printf '%s\n' "${a[@]}") <(printf '%s\n' "${b[@]}")

你能告诉我为什么我的命令不起作用吗?正则表达式的部分匹配会起作用吗?

编辑 1:更改数组a以包含可以从数组中包含多个代码的行b

rs6605071   chr1:962943 C   ENSG00000188976 ENST00000487214
rs6605071   chr1:962943 C   ENSG00000187961 ENST00000622660
rs6605071   chr1:962943 C   84069   NM_001160184.1
rs6605071   chr1:962943 C   339451  NC_006462594.2
rs6605071   chr1:962943 C   ENSG00000135234 ENST00000624144
rs6605071   chr1:962943 C   339451  XR_001737138.1
rs6605071   chr1:962943 C   334324  NC_006462632.2
rs6605071   chr1:962943 C   84333   NM_004353462.1
rs6605071   chr1:962943 C   339451  XM_006710600.3

预期输出:

rs6605071   chr1:962943 C   334324  NC_006462632.2
rs6605071   chr1:962943 C   339451  NC_006462594.2
rs6605071   chr1:962943 C   84069   NM_001160184.1
rs6605071   chr1:962943 C   84333   NM_004353462.1
rs6605071   chr1:962943 C   339451  XM_006710600.3
rs6605071   chr1:962943 C   339451  XR_001737138.1
rs6605071   chr1:962943 C   ENSG00000188976 ENST00000487214
rs6605071   chr1:962943 C   ENSG00000187961 ENST00000622660
rs6605071   chr1:962943 C   ENSG00000135234 ENST00000624144

编辑 2:由于下面 RavinderSingh13 提供的答案没有完全回答我的问题,我将重新询问有关如何使用 AWK 执行此类任务的问题。

提前致谢。

标签: arraysbashawk

解决方案


我在这里假设您想按顺序打印两个数组的匹配字段,然后您也想打印数组 a 中剩余的不匹配项,如果是这种情况,那么下面的内容可能会对您有所帮助。

在此处创建数组:

declare -a a=("rs6605071   chr1:962943 C   ENSG00000188976 ENST00000487214
rs6605071   chr1:962943 C   ENSG00000187961 ENST00000622660
rs6605071   chr1:962943 C   84069   NM_001160184.1
rs6605071   chr1:962943 C   339451  NC_006462594.2
rs6605071   chr1:962943 C   339451  XR_001737138.1
rs6605071   chr1:962943 C   339451  XM_006710600.3")
declare -a b=("NC
NG
NM
NP
NR
XM
XP
XR
WP")

现在运行以下代码:

awk -v OFS='\t' '
FNR==NR{
  split($5,a,"_")
  array[a[1]]=$0
  next
}
($1 in array) {
  print array[$0]
  b[$1]
}
END{
  for(i in b){
    delete array[i]
  }
  for(j in array){
    print array[j]
  }
}' <(printf '%s\n' "${a[@]}") <(printf '%s\n' "${b[@]}")

输出如下。

rs6605071   chr1:962943 C   339451  NC_006462594.2
rs6605071   chr1:962943 C   84069   NM_001160184.1
rs6605071   chr1:962943 C   339451  XM_006710600.3
rs6605071   chr1:962943 C   339451  XR_001737138.1
rs6605071   chr1:962943 C   ENSG00000188976 ENST00000487214
rs6605071   chr1:962943 C   ENSG00000187961 ENST00000622660

推荐阅读