【问题标题】:Merge two files based on common string in column, and fill in missing values for mismatches根据列中的公共字符串合并两个文件,并填写不匹配的缺失值
【发布时间】:2021-02-19 13:40:18
【问题描述】:

文件 1:

rs30051 102098 0|0 0|1 0|0 0|0 0|0 0|0
rs44619 103300 0|0 0|0 1|0 0|0 0|0 0|0
rs62418 103585 1|0 0|0 1|0 0|0 0|0 0|0
rs33155 105222 0|1 1|0 0|0 0|0 1|0 0|1

文件 2:

rs86792 101580 0|0 0|0 0|0 1|0
rs30051 102098 0|1 0|0 0|0 1|0
rs44619 103300 0|1 0|0 0|0 0|0
rs33155 105222 0|0 0|0 1|0 0|0 
rs27799 105943 0|1 1|1 0|0 0|0

合并后的文件需要在第 2 列进行排序。文件 1 和文件 2 中的所有数据必须保留在输出文件中。如果(例如)在文件 2 中找到某个列 1 标识符,但在文件 1 中找不到,则将文件 2 的第 1 列和第 2 列打印到输出文件,然后是文件 1 中缺失值的 6 x 0|0,后跟来自文件 2 的 4 x 值(用于在文件 1 中找不到的标识符)。所需的输出文件:

rs86792 101580 0|0 0|0 0|0 0|0 0|0 0|0 0|0 0|0 0|0 1|0
rs30051 102098 0|0 0|1 0|0 0|0 0|0 0|0 0|1 0|0 0|0 1|0
rs44619 103300 0|0 0|0 1|0 0|0 0|0 0|0 0|1 0|0 0|0 0|0
rs62418 103585 1|0 0|0 1|0 0|0 0|0 0|0 0|0 0|0 0|0 0|0
rs33155 105222 0|1 1|0 0|0 0|0 1|0 0|1 0|0 0|0 1|0 0|0
rs27799 105943 0|0 0|0 0|0 0|0 0|0 0|0 0|1 1|1 0|0 0|0

最好使用 awk 命令,并且非常感谢您的解释。填写缺失值使这个问题与我在本网站上找到的任何问题都不同。到目前为止我的代码(不起作用):

awk 'FNR==NR{a[$1]=$2; next}{ print $0, a[$1]}' file1 file2 | sort -k 2 > output.file

【问题讨论】:

    标签: arrays awk merge


    【解决方案1】:

    如果前两列的宽度固定,类似于输入中显示的示例,这里是awk+sort 解决方案。我用这些工具的GNU 版本对其进行了测试,但我觉得它也应该适用于其他实现。

    $ cat script.awk
    {
        s1 = substr($0, 1, 14)
        s2 = substr($0, 15)
    }
    
    NR == FNR {
        a[s1] = s2
        next
    }
    
    {
        a[s1] = (s1 in a) ? a[s1] s2 : " 0|0 0|0 0|0 0|0 0|0 0|0" s2
    }
    
    END {
        for (k in a) {
            s3 = (gsub(/\|/, "|", a[k])) == 6 ? " 0|0 0|0 0|0 0|0" : ""
            print k a[k] s3
        }
    }
    

    调用脚本:

    $ awk -f script.awk file1 file2 | sort -k2,2n
    rs86792 101580 0|0 0|0 0|0 0|0 0|0 0|0 0|0 0|0 0|0 1|0
    rs30051 102098 0|0 0|1 0|0 0|0 0|0 0|0 0|1 0|0 0|0 1|0
    rs44619 103300 0|0 0|0 1|0 0|0 0|0 0|0 0|1 0|0 0|0 0|0
    rs62418 103585 1|0 0|0 1|0 0|0 0|0 0|0 0|0 0|0 0|0 0|0
    rs33155 105222 0|1 1|0 0|0 0|0 1|0 0|1 0|0 0|0 1|0 0|0
    rs27799 105943 0|0 0|0 0|0 0|0 0|0 0|0 0|1 1|1 0|0 0|0
    

    如果前两列的宽度可以不同,请使用 s1s2 代替:

        s1 = $1 FS $2
        s2 = $0
        sub(/^[^ ]+ [^ ]+/, "", s2)
    

    【讨论】:

      猜你喜欢
      • 2019-03-01
      • 2015-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2017-09-03
      相关资源
      最近更新 更多