我有两个文件。第一个是FileA,它由三个列(制表符分隔)组成,请参见下面的内容
FileA
House1 dog blue
House2 cat yellow
House3 bird red
House4 cow orange
House5 duck black
House6 cow brown
第二个是FileB,包含两个列(制表符分隔)FileB列1包含FileA列2中所有非常规值的列表。FileB列2包含我想要它们在Colum 1中的对应值的值的列表在FileA中替换为
FileB
dog 1
cat 2
cow 3
duck 4
bird 5
换句话说,我希望在FileA列2中找到与FileB列1匹配的所有值,并将它们替换为File B列2中的相应值,然后将新的FileA输出到新文件(“ FileA2” )
新FileA(FileA2)的输出应如下所示(即名称栏2已全部更改为数字,每次更改都对应于FileB中的查找替换条件)
House1 1 blue
House2 2 yellow
House3 5 red
House4 3 orange
House5 4 black
House6 3 brown
是否有awk,grep或sed单线可做到这一点?
注意:在现实生活中,我的“ FileA”在第2列中有800,000行和超过4000个唯一值,因此最好通过Linux终端来执行。
还有,是否有一种方法可以从给定文件的单个列中提取唯一值列表?
在此先感谢您的帮助。
答案 0 :(得分:0)
以下应该可以解决问题(bash
):
#!/usr/bin/env bash
join -t $'\t' \
<(sort -t $'\t' -k 2 FileA) \
<(sort -t $'\t' -k 1 FileB) \
-1 2 \
-2 1 | \
sort -t $'\t' -k 2 | \
awk -F '\t' 'BEGIN { OFS="\t" } {print $2, $4, $3}'
首先,需要对文件进行排序以使用join
命令:
sort -t $'\t' -k 2 FileA
sort -t $'\t' -k 1 FileB
在这里,我们根据第二列(FileA
)对-k 2
进行排序,并根据第一列(FileB
)对-k 1
进行排序。选项卡用于两个文件作为分隔符(-t $'\t'
)。
注意:可以在准备步骤中对输入进行排序(将排序后的结果存储在临时文件中),以避免在每次执行整个命令时对文件进行重新排序。
接下来,join
命令将参数用作:
-t $'\t'
)<(sort ...)
)-1 2
=第一个文件,第二列-2 1
=第二个文件,第一列加入后,要获得所需的输出(根据输入的第二列(包含House
的列进行排序),我们需要通过运行sort -t $'\t' -k 2
对上一个命令的输出进行排序
最后,awk
仅用于获取所需的列(按顺序依次为第二列,第四列和第三列),并以\t
(BEGIN { OFS="\t" }
)分隔。
此命令已在Linux主机上经过测试。您可以在与Docker相同的环境中测试此命令;在当前目录中,必须具有FileA
,FileB
和join.sh
(一个包含第一个命令的可执行脚本)。
正在运行:
docker run --rm -v $(pwd):/tmp -w /tmp debian:buster ./join.sh
返回:
House1 1 blue
House2 2 yellow
House3 5 red
House4 3 orange
House5 4 black
House6 3 brown