【问题标题】:mixing text files with all fields in awk将文本文件与 awk 中的所有字段混合
【发布时间】:2019-06-30 10:23:05
【问题描述】:

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

例子1:

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

例子2:

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

但结果不正确。你知道如何解决它吗?

【问题讨论】:

标签: awk


【解决方案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

【讨论】:

    【解决方案2】:

    再一次,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 这样的其他人没有,所以第一个版本更便携。

    【讨论】:

    • @JamesBrown 嗯。直到。可以发誓这种重定向是 POSIX 语法。
    • 甚至 ksh 也支持它,而 POSIX shell 就是基于它。也许它是在 ksh93 中添加的?哦,好吧。
    【解决方案3】:

    排序 + 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
    
    $
    

    【讨论】:

      猜你喜欢
      • 2012-02-01
      • 1970-01-01
      • 2015-01-25
      • 1970-01-01
      • 2011-04-26
      • 2014-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多