Bash 如何合并两个选项卡分隔的文件并预定义缺少值的格式?
我试图通过一列部分重叠的标识符(gene#)合并两个未排序的制表符分隔的文件,并选择预定义缺少的值并保持第一个表的顺序 在我的两个示例表上使用Bash 如何合并两个选项卡分隔的文件并预定义缺少值的格式?,bash,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
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 gene4 gene4 1.05 0.5
c1 300 400 gene1 gene1 4.2 0.001
c13 600 700 gene2 NA 1 1
我假设一种方法是构建一个
awk
条件构造。如果您能为我指出正确的方向,那就太好了。使用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
这将产生:
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
awk'FNR==NR{a[$1]=1;b[$1]=2;c[$1]=3;next}
{如果(!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]}
'文件2文件1
[解释]
- 在第1行中,
是一种仅在读取参数列表中的第一个文件时执行命令的习惯用法(在本例中为“file2”)。然后它创建映射(又称关联数组),将“file2”中的值关联到FNR==NR{command;next}
基因
- 没有必要对“file2”进行排序
- 以下行仅在读取第二个文件(“文件1”)时执行,因为由于
语句,在读取第一个文件时跳过了这些行next
- 当关联数组
未定义时,a[gene]
行是将变量分配给默认值的回退(这意味着在“file2”中找不到{if(!a[$4])…
基因)
- 最后一行通过
打印“file1”的内容,后跟相关值基因
- 使用
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
这将产生:
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
awk'FNR==NR{a[$1]=1;b[$1]=2;c[$1]=3;next}
{如果(!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]}
'文件2文件1
[解释]
- 在第1行中,
是一种习惯用法,用于仅在读取参数列表中的第一个文件时执行命令(在本例中为“file2”)。然后创建映射(也称为关联数组),将“file2”中的值与FNR==NR{command;next}
基因关联
- 没有必要对“file2”进行排序
- 以下行仅在读取第二个文件(“文件1”)时执行,因为由于
语句,在读取第一个文件时跳过了这些行next
- 当关联数组
未定义时,a[gene]
行是将变量分配给默认值的回退(这意味着在“file2”中找不到{if(!a[$4])…
基因)
- 最后一行通过
打印“file1”的内容,后跟相关值基因
- 您可以使用
加入:
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-
您可以使用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-
虚线的最后一个字符是制表符。请使用
paste file1 file2 | sed 's/\t$/\tNA\t1\t1/g'
虚线的最后一个字符是制表符。请使用
paste file1 file2 | sed 's/\t$/\tNA\t1\t1/g'
gene1
应该连接到gene1
吗?或者您只是试图将na11
附加到file2
中,直到它的行数与file1
相同?要使用join
必须对文件进行排序。是的,应该使用gene列进行连接。理想情况下,file1
应该逐行进行连接d检查file2
中任何一行中是否有匹配的基因条目。如果发现某些内容,则应附加file2的两个额外列,如果未发现任何内容,则应附加NA 1 1
。谢谢。我们可以对其进行排序吗?初始顺序重要吗?gene1
是否唯一(没有两行gene1
行?)?您可以使用排序与连接与-e“NA 1 1”
我们可以对其进行排序,如果这有帮助,我们可以在之后使用文件1
将其排序到原始顺序(第一列:c3、c1、c13
)作为某种排序键?基因绝对是唯一的。gene1
是否应该连接到gene1
,或者您只是试图将NA 1 1
附加到file2
,直到它与file1
具有相同的行数?要使用join
,必须对文件进行排序。是的,应该使用gene列d连接。理想情况下,应逐行检查file1
文件2
中任何一行中是否有匹配的基因条目。如果发现了某些内容,则应追加file2的两列,如果未发现任何内容,则应追加NA 1
。谢谢。我们可以对其排序吗?初始顺序重要吗?gene1
唯一(没有两行gene1
行?)?您可以使用sort
和join
和-e“NA 1 1 1”
对其进行排序,如果这有帮助,我们可以对其进行排序,当然我们可以使用file1
将其排序到原始顺序(第一列:c3、c1、c13
)作为某种排序键?基因绝对是独一无二的。谢谢你的回答和解释。在我的示例代码中,它是有效的,但是当我用我的分析案例尝试它时,我得到以下错误消息:join:file 1未按排序顺序
join:file 2未按排序顺序
知道问题是什么吗通过改变基因列的顺序来调整上面的例子,现在生成了一个类似的错误join:file 1没有按排序顺序
@gdeniz我想这是可以解决的,无需对file1
进行排序,因为在我的现实世界中file1
是生成特定数据的聚类程序的结果ta依赖顺序?@gdeniz最后一次排序将恢复顺序。谢谢你的帮助