合并两个文件中的匹配列,或使用默认值

合并两个文件中的匹配列,或使用默认值

我正在尝试重写文件文本,主文件.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

我们漏掉了一行。再试一次并告诉jointo 也输出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

之后,将两者的输出组合起来,然后进行排序(参见答案顶部)。

相关内容