我正在尝试重写文件文本,主文件.txt变化自更改.txt。这主文件.txt文件是这样的:
word_1 genre_A
word_2 genre_A
word_3 genre_B
word_4 genre_C
word_5 genre_A
还有更改.txt是这样的:
genre_A root_A
genre_C root_C
我想更改其中的内容更改.txt在主文件.txt获得这样的东西:
word_1 root_A
word_2 root_A
word_3 genre_B
word_4 root_C
word_5 root_A
这些文件非常大,所以我需要一种自动方法。
我尝试加载所有变量更改.txt放在一个awk
数组中,如果不同则打印相同的内容,如果相同则更改。像这样的东西:
NR==FNR{a[$1,$2]++;next} $3==a[$1] {print $1,$2,a[$2]} $3!=a[$1] {print $1,$2,$3}
但我做错了什么。我也听说这可以通过命令来完成join
,但我不习惯,所以解释一下每个部分会很有帮助。
谢谢大家。
答案1
您提到了该join
命令,但在这种情况下使用它并不容易。至少它本身不是。
让我们尝试加入这两个文件。为此,首先需要在连接字段上对文件进行排序。我们将使用第一个文件中的第二个字段和join
第二个文件中的第一个字段(这是 的默认值):
$ sort -k2 -o main.txt main.txt
$ sort -k1 -o changes.txt changes.txt
然后我们进行连接:
$ join -1 2 main.txt changes.txt
genre_A word_1 root_A
genre_A word_2 root_A
genre_A word_5 root_A
genre_C word_4 root_C
我们漏掉了一行。再试一次并告诉join
to 也输出main.txt
那些否则会被忽略的行(因为它们与 中的任何内容都不匹配changes.txt
):
$ join -1 2 -a 1 main.txt changes.txt
genre_A word_1 root_A
genre_A word_2 root_A
genre_A word_5 root_A
word_3 genre_B
genre_C word_4 root_C
请注意,我们不能要求join
仅输出任一文件中的某些列,因为所需输出中的第二列包含两个文件中的数据的混合。
但是,通过上面的输出,我们可以使用一个简单的awk
脚本提取最后两列(我真希望cut
可以采用负字段规范来从右侧获取列!):
$ join -1 2 -a 1 main.txt changes.txt | awk '{ print $(NF-1), $NF }'
word_1 root_A
word_2 root_A
word_5 root_A
word_3 genre_B
word_4 root_C
通过管道将其传送到sort
进行排序:
$ join -1 2 -a 1 main.txt changes.txt | awk '{ print $(NF-1), $NF }' | sort
word_1 root_A
word_2 root_A
word_3 genre_B
word_4 root_C
word_5 root_A
答案2
awk命令:
awk 'NR==FNR {a[$1]=$2;next} {if ($2 in a) print $1,a[$2]; else print $1,$2}' changes.txt main.txt
输出:
word_1 root_A
word_2 root_A
word_3 genre_B
word_4 root_C
word_5 root_A
答案3
种类和加入(但不是awk) 方法:
sort -k2 main.txt > main_sort.txt ; \
sort -k1 changes.txt > changes_sort.txt ; \
{ join -i -1 2 -2 1 -o 1.1 2.2 main_sort.txt changes_sort.txt ; \
join -v 1 -i -1 2 -2 1 -o 1.1 1.2 main_sort.txt changes_sort.txt ; } | \
sort -g | column -t
输出:
word_1 root_A
word_2 root_A
word_3 genre_B
word_4 root_C
word_5 root_A
解释...
join
需要两个带有排序字段的文件。由于每个文件都很大并且需要使用两次,因此提前对两个文件进行排序会更有效。假设所有文件都是标签划定的。
种类主文件.txt由第二名领域(流派),以及更改.txt由第一名字段(根):
sort -k2 main.txt > main_sort.txt
sort -k1 changes.txt > changes_sort.txt
第 1 遍,输出匹配的行:
join -i -1 2 -2 1 -o 1.1 2.2 main_sort.txt changes_sort.txt
输出 4 行,按根场地:
word_1 root_A
word_2 root_A
word_5 root_A
word_4 root_C
旗帜join
“-1 2 -2 1”告诉它加入这第一名文件的第二场到第二名文件的第一的场地。旗帜“-o 1.1 2.2”告诉它打印这第一名文件的第一的场到第二名文件的第二场地。
通过2,使用“-v 1”标志输出缺失的行第一的文件:
join -v 1 -i -1 2 -2 1 -o 1.1 1.2 main_sort.txt changes_sort.txt
输出:
word_3 genre_B
之后,将两者的输出组合起来,然后进行排序(参见答案顶部)。