在同一个文件上进行多次替换 - awk

时间:2014-12-01 12:10:40

标签: perl replace awk

我正在尝试使用awk单线程脚本在同一文件上进行多次替换。 用于变量赋值的文件如下:

> cat names 
1 Dusky
2 Flag
3 Mon

我希望在此文件中进行替换:

> cat file.txt 
  1        1   0.6248 0.3752 
  2        2   0.0430 0.9570 
  3        3   0.0624 0.9376

我试过的是:

while read num name; do 
    awk -v J=$num -v R=$name '{if (match($1, J)) $2=R; print;}' file.txt; 
done < names

但是此代码打印了要替换的每一行的输入文件。

1 Dusky 0.6248 0.3752
  2        2   0.0430 0.9570 
  3        3   0.0624 0.9376 
  1        1   0.6248 0.3752 
2 Flag 0.0430 0.9570
  3        3   0.0624 0.9376 
  1        1   0.6248 0.3752 
  2        2   0.0430 0.9570 
3 Mon 0.0624 0.9376

如何让它只打印一次更换的线? 可以是awk或perl。

期望的输出:

1 Dusky 0.6248 0.3752
2 Flag 0.0430 0.9570
3 Mon 0.0624 0.9376

3 个答案:

答案 0 :(得分:5)

读取第一个文件并存储ID怎么样?然后,使用匹配的名称/ id替换第二个文件中的第二个字段。

awk 'FNR==NR {a[$1]=$2; next} {$2=a[$2]; print}' names f

对于您的给定输入,它返回:

1 Dusky 0.6248 0.3752
2 Flag 0.0430 0.9570
3 Mon 0.0624 0.9376

解释

  • FNR==NR {a[$1]=$2; next}在读取第一个文件时,将第二个字段存储在索引为第一个字段的数组中。这样,1映射到Dusky2Flag,...
  • {$2=a[$2]; print}在读取第二个文件时,将第二个字段替换为第一个文件中对应的id。然后,打印。这可以更加惯用地写为{$2=a[$2]}1

请注意,您可以添加安全检查:只需替换第二个文件中的第二个字段(如果它确实存在):

awk 'FNR==NR {a[$1]=$2; next} {if ($2 in a) $2=a[$2]} 1' names f

答案 1 :(得分:3)

从命令行使用perl,

perl -lane'
  BEGIN{ local @ARGV=pop; %h= map split,<> }
  $_ = $h{$_} //$_ for $F[1]; print "@F"
' file.txt names

输出

1 Dusky 0.6248 0.3752
2 Flag 0.0430 0.9570
3 Mon 0.0624 0.9376

答案 2 :(得分:1)

怎么样

$ awk 'NR==FNR{line[$1]=$2; next} {line[$1]=line[$1]" "$3" "$4} END{for( i in line) print i, line[i]}' names file
1 Dusky 0.6248 0.3752
2 Flag 0.0430 0.9570
3 Mon 0.0624 0.9376