Perl 同一文件上的多个替换-awk

Perl 同一文件上的多个替换-awk,perl,replace,awk,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=$

我正在尝试使用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
如何使替换的行只打印一次? 可以是awk或perl格式

期望输出:

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

$ 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

读取第一个文件并存储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
    被映射到
    dasky
    2
    标志
  • {$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

从命令行使用perl

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

那么您想用
名称中相应的名称替换
文件.txt中的第二列吗?列之间的分隔符是什么?没错。分隔符是空白,但它可以是多个分隔字段的空白。您甚至可以在第二个操作块后使用速记和
1
,而不是
print
。太好了。非常好的一行。这也表明我需要研究更多的FNR和NR变量…@PedroA给出了一个读数。你会在那里找到有趣的东西!可以缩短为
awk'FNR==NR{a[$1]=$2;在a{$2=a[$2]}1'
中的下一个}$2;或者假设数字是唯一的,可以在a&&$2=a[$2]中缩短为
awk'$2;{a[$1]=$2}'
感谢您提供的perl一行程序+1@PedroA如果
names
文件中没有第二列的编号,则第二列将保持不变。。一开始我发现$F[1]
$\uu=$h{$\u}/$\ u有点神秘,但后来我意识到
$\u
for
循环中的一个引用。因此它将等价于
$F[1]=$h{$F[1]}/$F[1]
。。仍然在学习Perl中的惊人技巧:)@HåkonHægland是的,$F[1]它通过使用
for
进行别名/主题化。有时在处理长变量或重复变量时,它可能很有用。
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