如何使用awk将一个文件中的数据替换为unix shell中第二个文件中的更新数据?

时间:2013-05-05 23:15:54

标签: unix

假设我有两个文件,文件1包含原始数据,而文件2(最近创建的文件)已更新了一些需要替换为文件1的数据的值。

以下是文件1格式的示例,其中包含10000行数据,如下所示:

1000001 aaaaaaa aaaaaaa 123
1000002 aaaaaab aaaaaab 123
.
.
.
1000503 xxxxxxa xxxxxxa 123
.
.
.
1010000 zzzzzzl zzzzzzl 123

文件2包含1054行,其更新值与文件1的格式相同,但其中许多行不连续。例如,文件2中的第1000503行将如下所示:

1000503 xxxxxxb xxxxxxb 245

2 个答案:

答案 0 :(得分:1)

这将使用joinawk进行,假设文件按键顺序排列:

join -a1 -j1 file1 file2 \
    | awk '{ if (NF > 4) print $1, $5, $6, $7; else print $0 }'

这完成了两次通过。

合并文件

首先,join采用两个具有公共列的文本文件(在本例中为您的前导数字列),并将它们“加入”,就像数据库连接一样。默认情况下,它会打印两个文件中出现密钥的所有行。 -j1告诉它加入第一个字段。 -a1告诉它打印文件1中的所有行,即使文件2中没有相应的行。

join确实有两个文件按键排序的限制。

这导致文件1的副本还包括文件2中的匹配行,如下所示:

1000001 aaaaaaa aaaaaaa 123
1000002 aaaaaab aaaaaab 123
.
.
.
1000503 xxxxxxa xxxxxxa 123 xxxxxxb xxxxxxb 245
.
.
.
1010000 zzzzzzl zzzzzzl 123

拆分字段

我们现在遇到一个问题:匹配的行包含两个文件的数据。但这不是我们想要的:我们希望它替换文件1中的数据。我无法看到让join单独执行此操作的方法,因此{ {1}}救援。

Awk代码非常简单。如果字段数(awk变量)大于4,我们有一个连接线;在这种情况下,打印字段1,5,6和7.否则,打印整个原始行(因为它未连接)。

这将发出未修改的每个不匹配的行,以及每个匹配行的file2版本。

答案 1 :(得分:1)

使用sed:

join -a 1 in1 in2 | sed 's/^\([0-9]*\) [^ ]* [^ ]* [^ ]* /\1 /'