将文本文件与awk中的所有字段混合

时间:2019-02-06 12:50:39

标签: awk

我有2个制表符分隔的文件,例如这些小示例:

example1:

RBM3    1517    993 -0.611355
RBM4    142 142 0
PRKAG1  146 73  -1
MORF4L2 1766    715 -1.30447

example2:

PCNP    370 139 -1.41244
RBM3    60  60  0
COTL1   338 252 -0.4236
PRKAG1  276 225 -0.294743

我想获取基于第1列的公共行(在两个文件中),并创建一个包含7列的新文件,其中第1列是原始文件中的第1列,第2、3和4列来自第一个文件以及第5、6和7列来自第二个文件(第2、3和4列)。这是预期的输出:

预期输出:

RBM3    1517    993 -0.611355   60  60  0
PRKAG1  146 73  -1  276 225 -0.294743

我正在尝试使用以下代码在AWK中做到这一点:

awk -v OFS="\t" 'NR==FNR {n[$2]=$1;next} ($2 in n) {print $1, $2, $3, $4, n[$2], n[$3], n[$4]}' file1 file2  > results.txt

,但结果不正确。你有什么办法解决吗?

3 个答案:

答案 0 :(得分:1)

这是一种方法:

$ awk -v OFS="\t" '
NR==FNR {              # file2
    k=$1               # set key
    $1=""              # nullify $1, OFS stays
    a[k]=$0            # hash record on k
    next
}
($1 in a) {            # file1, if $1 matches in a
    print $0 a[$1]     # output record and a
}' file2 file1         # mind the order
RBM3    1517    993     -0.611355       60      60      0
PRKAG1  146     73      -1      276     225     -0.294743

使用您的方法将类似于(未测试):

$ awk -v OFS="\t" '
NR==FNR {
    n[$1]=$2; o[$1]=$3; p[$1]=$4
    next
} 
($1 in n) {
    print $1, $2, $3, $4, n[$1], o[$1], p[$1]
}' file2 file1  > results.txt

答案 1 :(得分:1)

再一次,join比awk更好:

$ join -j1 <(sort -k1 file1.txt) <(sort -k1 file2.txt) | sed 's/ /\t/g'      
PRKAG1  146 73  -1  276 225 -0.294743
RBM3    1517    993 -0.611355   60  60  0

请参阅另一篇文章中的my answer,了解为什么要对文件进行排序;如果您正在使用我的解决方案来生成这些输入文件,则将对它们进行排序,您可以直接使用这些文件。这次使用sed来确保输出具有制表符分隔的列。


正如评论中指出的那样,某些shell(bash,zsh等)使您可以使用$'\t'来获取制表符。在这些上,您可以使用join -t $'\t' -j1 sortedfile1.txt sortedfile2.txt并保留sed位。但是,像dash这样的其他工具却没有,所以第一个版本更便于移植。

答案 2 :(得分:0)

sort + awk

sort elly1.txt elly2.txt | awk ' {c=$1; if(c==p) {$1=""; print c,a,$0 } p=c;$1="";a=$0 } ' | sed 's/ +/\t/g'

具有给定的输入

$ cat elly1.txt
RBM3    1517    993 -0.611355
RBM4    142 142 0
PRKAG1  146 73  -1
MORF4L2 1766    715 -1.30447

$ cat elly2.txt
PCNP    370 139 -1.41244
RBM3    60  60  0
COTL1   338 252 -0.4236
PRKAG1  276 225 -0.294743

$ sort elly1.txt elly2.txt | awk ' {c=$1; if(c==p) {$1=""; print c,a,$0 } p=c;$1="";a=$0 } ' | sed 's/ +/\t/g'
PRKAG1  146 73 -1  276 225 -0.294743
RBM3  1517 993 -0.611355  60 60 0

$