![根据第一列的匹配值替换文件列中的值](https://linux22.com/image/209569/%E6%A0%B9%E6%8D%AE%E7%AC%AC%E4%B8%80%E5%88%97%E7%9A%84%E5%8C%B9%E9%85%8D%E5%80%BC%E6%9B%BF%E6%8D%A2%E6%96%87%E4%BB%B6%E5%88%97%E4%B8%AD%E7%9A%84%E5%80%BC.png)
我有一个问题awk当第一列中的值匹配时,将 file1 中两列中的某些值替换为 file2 中的值。
这是一个例子:
我有:
file1
A 2012 3 B 2012 4 C 2012 9 D 2012 E 2012 7 F 2012
file2
D 2007 12 F 2009 8 G 2000 4
所需的输出是当第 1 列中的值匹配时我希望将第 2 列和第 3 列中的值替换为 file2 中的值,如下所示:
- 期望的输出:
A 2012 3 B 2012 4 C 2012 9 D 2007 12 E 2012 7 F 2009 8
我使用了这段代码,我知道它有问题
awk 'BEGIN{FS=",";OFS="\t"}
FNR==NR{a[$1]=$2;b[$1]=$3; next}
FNR>=1{if(a[$1]){print $0 }else{print $1, a[$1], b[$1] }}
' file2 file1
因为当我使用这段代码时,我获得的输出是:
A 2012 3
B 2012 4
C 2012 9
D 2012
E 2012 7
F 2012
这与 相同file1
。
有人可以向我解释这段代码有什么问题或建议替代解决方案吗?
答案1
问题有两个方面。
- 首先,您将输入字段分隔符设置为,
,
而您声明输入是空格分隔的。那么,您的任何现场操作都将无法正常进行。如果输入是空格分隔的,则实际上FS
根本不需要设置,因为awk
默认情况下会在“空白”处分割输入行(即任意数量的直接连续的空格和制表符)。 - 第二个问题在于你的状况
if (a[$1])
。如果当前行的第一列值file1
也存在于 中file2
,则这是正确的,但在您的代码中,您将打印 中 未更改的行,而不是替换您实际想要的file1
中 的值。file2
- 此外,您使用
print $0
打印输入行,其字段分隔符与从 读取的字段分隔符相同file1
,从而忽略OFS="\t"
这些行的指令。
相反,请使用以下内容:
awk 'BEGIN{OFS="\t"}
NR==FNR{col2[$1]=$2;col3[$1]=$3;next}
FNR>=1{if ($1 in col2) {$2=col2[$1];$3=col3[$1]} else {$1=$1}}1' file2 file1
将$1=$1
强制awk
使用实际的输出字段分隔符重新构建行,以便空格正确地替换为\t
。