我想基于"字符串字符串"替换文本。文件$ key中定义的对。
示例输入文件 $ input
a b c foo
d e f moo
g h i boo
Predefined" Key"档案 $ key
cow moo
code foo
ghost boo
cheer woo
期望输出
a b c code
d e f cow
g h i ghost
perl -pe 's/(.*?)(\woo)/$1qq{grep -oP ".*(?=\s$2)" $key}/e' $input > $output
错误返回
syntax error at -e line 1, near "$1qq{grep -oP ".*(?=\s$2)" $key}"
syntax error at -e line 1, near "s/(.*?)(\woo)/$1qq{grep -oP ".*(?=\s$2)" $key}/ee"
任何帮助都将不胜感激。
非常欢迎有关更好地实现所需结果的建议,但理想情况下, / p>
答案 0 :(得分:4)
从命令行使用perl,
perl -lane'
BEGIN{ local @ARGV = pop; %h = reverse map split, <> }
print join " ", @F[0..2], $h{$F[3]};
' input key
输出
a b c code
d e f cow
g h i ghost
更新
perl -lane'
BEGIN{ local @ARGV = pop; %h = reverse map /(.+)\s+(\S+)$/, <> }
print join " ", @F[0..2], $h{$F[3]};
' input key
答案 1 :(得分:3)
以下是使用awk
awk 'FNR==NR {a[$2]=$1;next} $NF=a[$NF]' key input
a b c code
d e f cow
g h i ghost
它将key
文件读取到数组a
然后使用数组input
的键打印a
文件以更改最后一个字段。
如果a[$NF]
可能是0
,请使用:
awk 'FNR==NR {a[$2]=$1;next} {$NF=a[$NF];print}' key input
答案 2 :(得分:3)
$1qq{grep -oP ".*(?=\s$2)" $key}
不是有效的Perl表达式。也许你的意思是
$1 . qq{grep -oP ".*(?=\s$2)" $key}
尽管该表达式中还有许多其他错误。 (您使用qq{}
,您应该使用qx{}
,忘记逃避\
,使用$key
而没有为其分配值,可能更多。)< / p>
只能读取密钥文件一次的可维护解决方案:
perl -e'
my %lookup;
open(my $fh, "<", shift(@ARGV))
or die $!;
while (<$fh>) {
my ($v,$k) = split;
$lookup{$k} = $v;
}
while (<>) {
my @f = split;
next if !@f; # Skip blank lines.
if (defined($lookup{$f[3]})) {
warn("Can'\''t find key \"$f[3]\". Copying record unchanged.\n");
print;
next;
}
$f[3] = $lookup{$f[3]};
print("@f\n");
}
' keyfile.txt input.txt >output.txt
答案 3 :(得分:2)
个人 - 我不喜欢做一个衬垫,因为它们很难读。
模式替换的一般技巧是:
my %replacements;
open ( my $keyfile, "<", "key_file.txt" ) or die $!;
while ( $keyfile ) {
chomp;
my ( $value, $key ) = split;
$replacements{$key} = $value;
}
my $regex = join ( "\b|\b", keys %replacements );
$regex = qr/$regex/;
open ( my $replace_fh, "<", "input_file" ) or die $!;
while ( <$replace_fh> ) {
s/\b($regex)\b/$replacements{$1}/g;
print;
}
将您的输入转换为替换的哈希值,构造匹配其中任何单词的正则表达式,然后使用该正则表达式“匹配” - 使用$1
哈希的查找键。