如何合并两个制表符分隔的文件并预定义缺少值的格式?

时间:2019-02-01 23:11:58

标签: bash

我正在尝试通过一列部分重叠的标识符(gene#)合并两个未排序的制表符分隔文件,并选择预定义缺失值并保持第一个表的顺序。

在我的两个示例表上使用paste时,缺少的值最终变成空白。

cat file1
c3  100 300 gene4
c1  300 400 gene1
c13 600 700 gene2

cat file2
gene1   4.2 0.001
gene4   1.05    0.5

paste file1 file2
c3  100 300 gene1   gene1   4.2 0.001
c1  300 400 gene4   gene4   1.05    0.5
c13 600 700 gene2

如您所见,结果并不出人意料地在不匹配的行中显示空白。有没有一种方法可以保持file1的顺序并像第三条一样填充行,如下所示:

c3  100 300 gene1   gene1   4.2 0.001
c1  300 400 gene4   gene4   1.05    0.5
c13 600 700 gene2   NA   1    1

我认为一种方法可以是建立一个awk条件构造。如果您能指出正确的方向,那就太好了。

3 个答案:

答案 0 :(得分:1)

使用https://docs.google.com/document/d/abc_xyz/preview ,请尝试以下操作:

awk

产生:

awk 'FNR==NR {a[$1]=$1; b[$1]=$2; c[$1]=$3; next}
    {if (!a[$4]) {a[$4]="N/A"; b[$4]=1; c[$4]=1}
     printf "%s  %s  %s  %s\n", $0, a[$4], b[$4], c[$4]}
' file2 file1

AWK“FNR == NR {A [$ 1] = $ 1; b [$ 1] = $ 2; c [$ 1] = $ 3;下一个}     {如果{A [$ 4] = “N / A”(一个[$ 4]!); b [$ 4] = 1; c [$ 4] = 1}      printf的 “%S%S%S%S \ n”,$ 0,则[$ 4],B [$ 4],C [$ 4]} “file2的文件1

[说明]

  • 在第一线,c3 100 300 gene1 gene1 4.2 0.001 c1 300 400 gene4 gene4 1.05 0.5 c13 600 700 gene2 N/A 1 1 是读取所述参数列表中的第一文件(在这种情况下,“文件2”)仅当要执行的命令的习惯用法。然后它会在“文件2”的地图(又名关联数组),以准值以FNR==NR { command; next}

为:

genes
  • 不必对“ file2”进行排序。

  • 以下各行仅读取第二文件(“文件1”)时,因为读取第一文件时,由于gene1 => gene1 (with array a) gene1 => 4.2 (with array b) gene1 => 0.001 (with array c) gene4 => gene4 (with array a) gene4 => 1.05 (with array b) gene4 => 0.5 (with array c) 语句这些行被跳过执行。

  • 当未定义关联数组next(意味着在{file2“中找不到{if (!a[$4]) ..时),行a[gene]是将变量分配给默认值的后备选项。

  • 在最终行打印 “文件1” 经由gene

  • 接着相关联的值的内容

答案 1 :(得分:1)

您可以使用join

join -e NA -o '1.1 1.2 1.3 1.4 1.5 2.1 2.2 2.3' -a 1 -1 5 -2 1 <(nl -w1 -s ' ' file1 | sort -k 5) <(sort -k 1 file2) | sed 's/NA\sNA$/1 1/' | sort -n | cut -d ' ' -f 2-

-e NA-用NA

替换所有缺失的值

-o ... —输出格式(使用<file>.<field>指定字段)

-a 1-保留左侧文件中的每一行

-1 5-2 1-用于联接文件的字段

file1file2-文件

nl -w1 -s ' ' file1-带编号行的file1

<(sort -k X fileN)-准备将文件N加入X列

s/NA\sNA$/1 1/ —用NA NA

替换行尾的每个1 1

| sort -n | cut -d ' ' -f 2--按数字排序并删除第一列


上面的示例在输出中使用空格。要使用标签,请附加| tr ' ' '\t'

join -e NA -o '1.1 1.2 1.3 1.4 2.1 2.2 2.3' -a 1 -1 4 -2 1 file1 file2 | sed 's/NA\sNA$/1 1/' | tr ' ' '\t'

答案 2 :(得分:0)

虚线以TAB作为最后一个字符。使用

修复此问题
paste file1 file2 | sed 's/\t$/\tNA\t1\t1/g'