我有 2 个文件,第一行是标题行供参考
file1
userId userContact parentId parentContact 200 0900200 100 - 201 0900201 100 - 300 0900300 101 -
file2
userId userContact parentId parentContact 100 0900100 100 - 101 0900101 100 -
我想填充 的第四列file1
,以便它必须搜索$3
in file1
,然后用from代替 of $1
,因此 输出应如下所示:file2
$2
file2
$4
file1
output
userId userContact parentId parentContact 200 0900200 100 0900100 201 0900201 100 0900100 300 0900300 101 0900101
我更喜欢awk
,因为它会更快。
答案1
使用join
(它需要排序的输入文件,因此我们传递了排序的输入)。
join -1 3 -2 1 -o 1.1,1.2,1.3,2.2 <(sort -k3 file1) <(sort file2)
200 0900200 100 0900100
201 0900201 100 0900100
300 0900300 101 0900101
with -1 3
, join 从第一个输入文件 (file1) 选择第三列作为键, with从第二个输入文件 (file2)-2 1
选择第一列作为键;然后它-o
输出这些列<文件#>.<列#>。
如果您的输入是制表符分隔的文件,请添加-t$'\t'
到 join 命令以及sort -k3 file1
.
如果您希望打印标题行,请head -n1 file1;
在连接之前添加。
或者使用awk
:
awk 'NR==FNR{ parentId[$1]=$2; next }
FNR>1 { $4=parentId[$3] }1' file2 file1
答案2
$ awk 'NR==FNR { keep[$1] = $2 ; next};
FNR==1 {print;next};
{ $4 = keep[$3]; print }' file2 file1
userId userContact parentId parentContact
200 0900200 100 0900100
201 0900201 100 0900100
300 0900300 101 0900101
这会读入file2
,将每行的字段 2 存储在名为 的数组中keep
(由字段 1 的值索引)。一旦完成读取file2
,它就开始读取file1
。它打印第一行(标题行),然后对于每个后续输入行,它将字段 4 更改为中的值keep[$3]
并打印它。
该脚本file2
通过NR==FNR
测试来检测它是否正在读取。 awk 的FNR
变量包含当前文件的当前行号,同时NR
包含迄今为止读取的所有文件的累积总行号。因此,如果 FNR 等于 NR,则我们正在读取第一个文件(即file2
- 这就是为什么它必须被列为第一个文件名 arg)。在一些相当模糊的情况下,此测试效果不佳,但对于大多数情况(包括这个)来说都很好。
如果需要更改输入或输出字段分隔符,可以使用 awk 的 -F 和 -v 选项。例如-F'\t'
和/或-v OFS='\t'
。