Bash 如何正确合并制表符分隔的文件
如果我有以下两个文件:Bash 如何正确合并制表符分隔的文件,bash,awk,merge,Bash,Awk,Merge,如果我有以下两个文件: 00001 missing affected 0.0132 case 00002 missing not affected 0.042 control 00003 missing affected 0.12 case 00004 present case 00005 missing
00001 missing affected 0.0132 case
00002 missing not affected 0.042 control
00003 missing affected 0.12 case
00004 present case
00005 missing affected 0.001 control
如何通过每个文件的第一列和最后一列连接这两个表,以便得到如下结果:
00001 missing affected 0.0132 case A 406 R
00002 missing not affected 0.042
00003 missing affected 0.12
00004 present case N/A 102
00005 missing affected 0.001 control 00005 C
请注意,第二个表中的00003缺失,第二个表中的第2行与表1中的case列不一致,因此这实际上是一个左联接的SQL等价物
谢谢。首先将输入中的字段分隔符更改为与空格不同的分隔符(因为空格在
中,不受影响
)。因此,假设输入如下(merge1.csv):
和(merge2.csv):
现在
的内容进行排序。首先将输入中的字段分隔符更改为与空格不同的内容(因为空格位于不受影响的中)。因此,假设输入如下(merge1.csv):
和(merge2.csv):
现在
从第1列和第5列中创建一个排序键,并使用类似于的内容对其进行排序。我不清楚获得该输出的算法是什么(例如,为什么00005
是输出最后一行中的第二个字段?)研究一下左连接的SQL等价物的意思比我的薪水高,但希望这能让你接近:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR { a[$1,$NF] = $0; next }
{
split(a[$1,$NF],b)
$NF = b[5] OFS b[2] OFS b[3] OFS b[4]
print
}
$ awk -f tst.awk file2 file1
00001 missing affected 0.0132 case A 406 R
00002 missing not affected 0.042
00003 missing affected 0.12
00004 present case N/A 102
00005 missing affected 0.001 control C
这样您就可以看到选项卡在上面的位置排列:
$ awk -f tst.awk file2 file1 | column -s$'\t' -t
00001 missing affected 0.0132 case A 406 R
00002 missing not affected 0.042
00003 missing affected 0.12
00004 present case N/A 102
00005 missing affected 0.001 control C
如果你编辑你的问题来包含你希望实现的任何算法的伪代码,那么我相信有人可以帮你把它翻译成awk
此外,如果文件1中可能缺少一个键字段,但该字段出现在文件2中,那么请将该情况包含在示例输入/输出中,以便我们可以看到您希望如何处理该问题。我不太清楚获得该输出的算法是什么(例如,00005
为什么是输出最后一行的第二个字段?)研究一下左连接的SQL等价物的意思比我的薪水高,但希望这能让你接近:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR { a[$1,$NF] = $0; next }
{
split(a[$1,$NF],b)
$NF = b[5] OFS b[2] OFS b[3] OFS b[4]
print
}
$ awk -f tst.awk file2 file1
00001 missing affected 0.0132 case A 406 R
00002 missing not affected 0.042
00003 missing affected 0.12
00004 present case N/A 102
00005 missing affected 0.001 control C
这样您就可以看到选项卡在上面的位置排列:
$ awk -f tst.awk file2 file1 | column -s$'\t' -t
00001 missing affected 0.0132 case A 406 R
00002 missing not affected 0.042
00003 missing affected 0.12
00004 present case N/A 102
00005 missing affected 0.001 control C
如果你编辑你的问题来包含你希望实现的任何算法的伪代码,那么我相信有人可以帮你把它翻译成awk
此外,如果文件1中可能缺少一个键字段,但该字段出现在文件2中,那么请将该情况包含在示例输入/输出中,以便我们可以看到您希望如何处理该问题。您可以使用此awk:
awk 'BEGIN{FS=OFS="\t"} {
k = $1 FS $NF
} FNR==NR {
gsub("^" $1 FS "|" FS $NF "$", "")
a[k] = $0
next
} {
$NF = (k in a) ? $NF OFS a[k] : ""
} 1' file2 file1 |
column -s $'\t' -t
column-s$'\t'-t
用于将输出格式化为表格格式
00001 missing affected 0.0132 case A 406 R
00002 missing not affected 0.042
00003 missing affected 0.12
00004 present case N/A 102
00005 missing affected 0.001 control C
您可以使用此awk:
awk 'BEGIN{FS=OFS="\t"} {
k = $1 FS $NF
} FNR==NR {
gsub("^" $1 FS "|" FS $NF "$", "")
a[k] = $0
next
} {
$NF = (k in a) ? $NF OFS a[k] : ""
} 1' file2 file1 |
column -s $'\t' -t
column-s$'\t'-t
用于将输出格式化为表格格式
00001 missing affected 0.0132 case A 406 R
00002 missing not affected 0.042
00003 missing affected 0.12
00004 present case N/A 102
00005 missing affected 0.001 control C
请显示您的编码工作。您可以先为每个文件创建一个“人工”前导字段,以便简单地join
ing结果:awk'{print$1$NF,$0}'
请显示您的编码工作。您可以先创建一个“人工”前导字段prep for simplyjoin
ing结果中每个文件的前导字段:awk'{print$1$NF,$0}'
没有理由更改字段分隔符-选项卡与分号一样合理且易于处理。只需使用BEGIN{FS=OFS=“\t”}
@EdMorton复制/粘贴提供的示例,结果是空格,而不是制表符。因此,获得一个不同于空格的分隔符的步骤。
还有一个额外的好处,那就是我们可以看到正在发生的事情,尤其是当某些列中存在缺失/空值时。啊,你的意思是他应该更改它,以便为这个问题提供示例输入/输出,而不是他应该在实际应用程序中更改它。好的,很公平。没有理由改变字段分隔符-制表符和分号一样合理和容易处理。只需使用BEGIN{FS=OFS=“\t”}
@EdMorton复制/粘贴提供的示例,结果是空格,而不是制表符。因此,获得一个不同于空格的分隔符的步骤。
还有一个额外的好处,那就是我们可以看到正在发生的事情,尤其是当某些列中存在缺失/空值时。啊,你的意思是他应该更改它,以便为这个问题提供示例输入/输出,而不是他应该在实际应用程序中更改它。好的,很公平。FWIW您可以替换s=$0;sub($1 FS,”,s);分包(FS$NF,”,s);a[k]=s
带gsub(“^”1fs | FS$NF“$”,”);a[k]=$0
甚至gsub(/^[^\t]+\t |\t+[^\t]+/,”);a[k]=$0}
如果$1和$NF中可能有RE元字符。更重要的是-SEP
是未定义的,因此您将这两个字段串联起来,这通常是“一件坏事”(ab c
和a bc
->abc
)。您可以使用SUBSEP或FS来代替SEP。不客气,您确实应该做些事情来解决SEP未定义的问题-或者使用已定义的内容,或者如果您确实想将它们连接起来(不推荐),那么就去掉SEP,因为它会误导您。实际上,这里并不真正需要SEP
,甚至FS
也可以用作两个连接键之间的分隔符。@anubhava是的,我在第一条评论中说可以用subsp或FS来代替。@brucezepplin:很高兴它能起作用。我对它进行了轻微的更新,以在output.FWIW中生成更好的格式,您可以替换s=$0;sub($1 FS,”,s);分包(FS$NF,”,s);a[k]=s
带gsub(“^”1fs | FS$NF“$”,”);a[k]=$0
甚至gsub(/^[^\t]+\t |\t+[^\t]+/,”);a[k]=$0}
如果$1和$NF中可能有RE元字符。更重要的是-SEP
是未定义的,因此您将这两个字段串联起来,这通常是“一件坏事”(ab c
和a bc
->abc
)。您可以使用SUBSEP或FS代替SEP。不客气,您确实应该对SEP未定义的问题采取一些措施-或者使用已定义的内容,或者如果您真的想将它们连接起来(不推荐),那么就去掉SEP,因为它会误导您。实际上SEP