通过匹配特定列来连接两个文件

Join two files by matching a specific column

我正在尝试合并两个已排序的文件

文件 1

70 CBLB Cbl proto-oncogene B
70 HOXC11 centrosomal protein 57
70 CHD4 chromodomain helicase
70 FANCF FA complementation
70 LUZP2 leucine zipper protein 2

文件 2

0.700140820757797 ELAVL1
0.700229616476825 HOXC11
0.700328646327188 CHD4
0.700328951649384 LUZP2

输出

Gene Symbol  Gene Description         Target Score mirDB   Target Score Diana
HOXC11       centrosomal protein 57   70                   0.700229616476825
CHD4         chromodomain helicase    70                   0.700328646327188
LUZP2        leucine zipper protein 2 70                   0.700328951649384

为了执行此任务,我尝试使用此脚本,但它 returns 是一个空文件

join -j 2 -o 1.1,1.2,1.3,1.4,2.4 File1 File2 | column -t | sed '1i Gene Symbol, Gene 
Description, Target Score mirDB, Target Score Diana' > Output

请求有关 awk 或 join 命令的任何帮助。

你可以试试这个awk

$ awk 'BEGIN {OFS="\t"; print "Gene Symbol", "Gene Description", "Target Score mirDB", "Target Score Diana"} NR==FNR{array[]=; next} [=10=]!~array[]{print ,OFS " "" ",, ,OFS array[]}' file2 file1

Gene Symbol     Gene Description        Target Score mirDB      Target Score Diana
HOX11           centrosomal protein 57          70              0.700229616476825
CHD4            chromodomain helicase           70              0.700328646327188
LUZP2           leucine zipper protein  2       70              0.700328951649384
BEGIN {
    OFS="\t" 
    print "Gene Symbol", "Gene Description", "Target Score mirDB", "Target Score Diana"
} NR==FNR {
    array[]=
    next
} [=11=]!~array[] {
    print ,OFS " "" ",, ,OFS array[]
}

更新: 更新了 awk 以删除 Windows 行结尾 (\r),因为这在 [=50] 期间作为问题弹出=] 与 OP


问题:

  • OP 的当前代码需要在调用 join
  • 之前对两个文件进行预排序
  • 由于 File1 中白色 space 分隔列的数量可变,因此很难(不可能?)让 join 生成一种不会出现的格式被后续 column 通话打乱
  • column 无法区分用作字段分隔符的 space 与用作字段一部分的 spaces

由于这些问题,我认为 awk 解决方案结合 column 进行 'easy' 重新格式化,更易于实施和理解,例如:

awk '
BEGIN      { OFS="|"                              # "|" will be used as the input delimiter for a follow-on "column" call
             print "Gene Symbol", "Gene Description", "Target Score mirDB", "Target Score Diana"
           }
           { sub(/\r/,"") }                       # remove Windows line ending "\r" for all lines in all files
FNR==NR    { gene[]= ; next }
 in gene { lastF=pfx=""
             for (i=3;i<=NF;i++) {                # pull fields #3 to #NF into a single variable 
                 lastF=lastF pfx $i
                 pfx=" "
             }
             print , lastF, , gene[]
           }
' File2 File1 

这会生成:

Gene Symbol|Gene Description|Target Score mirDB|Target Score Diana
HOXC11|centrosomal protein 57|70|0.700229616476825
CHD4|chromodomain helicase|70|0.700328646327188
LUZP2|leucine zipper protein 2|70|0.700328951649384

虽然可以添加更多代码以便 awk 在 'pretty' 列中打印输出,但我选择了一种更简单的方法让 column 执行额外的操作工作:

awk '
BEGIN      { OFS="|" 
             print "Gene Symbol", "Gene Description", "Target Score mirDB", "Target Score Diana"
           }
           { sub(/\r/,"") }                       # remove Windows line ending "\r" for all lines in all files
FNR==NR    { gene[]= ; next }
 in gene { lastF=pfx=""
             for (i=3;i<=NF;i++) {
                 lastF=lastF pfx $i
                 pfx=" "
             }
             print , lastF, , gene[]
           }
' File2 File1 | column -s'|' -t

这会生成:

Gene Symbol  Gene Description          Target Score mirDB  Target Score Diana
HOXC11       centrosomal protein 57    70                  0.700229616476825
CHD4         chromodomain helicase     70                  0.700328646327188
LUZP2        leucine zipper protein 2  70                  0.700328951649384

这可能对您有用(GNU sed、连接和列):

( echo 'Gene Symbol@Gene Description@Target Score mirDB@Target Score Diana';
join -j2 -t@ --no -o 0,1.3,1.1,2.1 <(sed 's/ /@/;s//@/' file1) <(sed 's/ /@/' file2) ) |
column -s@ -t

制定最终标题,连接两个输入文件,并将总输出传递给列命令,将结果制成表格。

N.B。标题由 @ 分隔,这是一个在标题或连接文件中找不到的任意字符。输入文件被修改,以便它们的字段分隔符与标题的字段分隔符匹配,并且 column 命令使用相同的分隔符来制表最终结果。 --no--nocheck-order 的缩写)阻止警告消息。