这个问题类似于my last one,但有一个区别是让玩具脚本与我的实际脚本更相似。
这是玩具脚本,replace.pl(编辑:现在使用'use strict;'等)
#! /usr/bin/perl -w
use strict;
open(REPL, "<", $ARGV[0]) or die "Couldn't open $ARGV[0]: $!!";
my %replacements;
while(<REPL>) {
chomp;
my ($orig, $new, @rest) = split /,/;
# Processing+sanitizing of orig/new here
$replacements{$orig} = $new;
}
close(REPL) or die "Couldn't close '$ARGV[0]': $!";
print "Performing the following replacements\n";
while(my ($k,$v) = each %replacements) {
print "\t$k => $v\n";
}
open(IN, "<", $ARGV[1]) or die "Couldn't open $ARGV[1]: $!!";
while ( <IN> ) {
while(my ($k,$v) = each %replacements) {
s/$k/$v/gee;
}
print;
}
close(IN) or die "Couldn't close '$ARGV[1]': $!";
所以,现在假设我有两个文件,replacements.txt(使用上一个问题的最佳答案,加上不使用替换的替换对):
(f)oo,q($1."ar")
cat,hacker
和test.txt:
foo
cat
当我运行perl replace.pl replacements.txt test.txt
时,我希望输出为
far
hacker
但是它是'$1."ar"
'(过多的转义)但结果却不算什么(即使是替换字符串的答案中的其他建议)。 foo
变为ar,猫/黑客对空字符串进行评估,似乎。
那么,我需要对replace.pl和/或replacements.txt进行哪些更改?其他人会创建replacements.txt,所以我想让这个文件尽可能简单(尽管我承认我正在打开它们的正则表达式)。
如果无法一步完成,我将使用宏来枚举此特定文件的所有可能的替换对,并希望问题不再出现。
答案 0 :(得分:4)
请不要向我们提供不使用严格和警告的非工作玩具脚本。因为人们在调试中要做的第一件事就是打开它们,而你刚刚开始工作。
第二个提示,使用open参数的3参数版本而不是2参数版本。它更安全。另外在你的错误检查中,按照perlstyle说(请参阅http://perldoc.perl.org/perlstyle.html获取完整建议)并包含文件名和$!。
无论如何,你的问题是你所包含的代码是q($ 1。“ar”)。执行时,返回字符串$ 1.“ar”。摆脱q(),它工作正常。 但是会引发警告。这可以通过将引用移动到替换脚本和原始脚本中来解决。
这是一个固定的脚本:
#! /usr/bin/perl -w
use strict;
open(REPL, "<", $ARGV[0]) or die "Couldn't open '$ARGV[0]': $!!";
my %replacements;
while(<REPL>) {
chomp;
my ($orig, $new) = split /,/;
# Processing+sanitizing of orig/new here
$replacements{$orig} = '"' . $new . '"';
}
close(REPL) or die "Couldn't close '$ARGV[0]': $!";
print "Performing the following replacements\n";
while(my ($k,$v) = each %replacements) {
print "\t$k => $v\n";
}
open(IN, "<", $ARGV[1]) or die "Couldn't open '$ARGV[1]': $!!";
while ( <IN> ) {
while(my($k,$v) = each %replacements) {
s/$k/$v/gee;
}
print;
}
close(IN) or die "Couldn't close '$ARGV[1]': $!";
修改后的replacements.txt是:
(f)oo,${1}ar
cat,hacker
答案 1 :(得分:0)
自上一个问题以来,您已经引入了一个插值级别。 您可以通过以下方式获得正确的结果:
在替换上放置第3个“e”修饰符
s/$k/$v/geee; # eeek
通过制作第一行
,在replacements.txt
中移除一层插值
(f)oo,$1."ar"
答案 2 :(得分:0)
删除替换字符串中的q();
应该只是
(f)oo,$1."ar"
如($k,$v) = split /,/, $_;
警告:在evals中使用外部输入数据非常非常危险
或者,只是让它成为
(f)oo,"${1}ar"
无论如何都不需要修改代码,例如小号///吉。
编辑 @drhorrible,如果它不起作用,那么你还有其他问题。
use strict;use warnings;
my $str = "foo";
my $repl = '(f)oo,q(${1}."ar")';
my ($k,$v) = split /,/, $repl;
$str =~ s/$k/$v/gee;
print $str,"\n";
$str = "foo";
$repl = '(f)oo,$1."ar"';
($k,$v) = split /,/, $repl;
$str =~ s/$k/$v/gee;
print $str,"\n";
$str = "foo";
$repl = '(f)oo,"${1}ar"';
($k,$v) = split /,/, $repl;
$str =~ s/$k/$v/gee;
print $str,"\n";
输出:
${1}."ar"
far
far