Man*_*anu 45 regex perl substitution
我想做以下事情:
$find="start (.*) end";
$replace="foo \1 bar";
$var = "start middle end";
$var =~ s/$find/$replace/;
Run Code Online (Sandbox Code Playgroud)
我希望$ var包含"foo middle bar",但它不起作用.也不是:
$replace='foo \1 bar';
Run Code Online (Sandbox Code Playgroud)
不知怎的,我错过了关于逃避的事情.
我修复了失踪的's'
yst*_*sth 76
在替换方面,您必须使用$ 1,而不是\ 1.
并且你只能通过使替换成为一个可以提供所需结果的可转换表达式来执行你想要的操作,并告诉s ///使用/ ee修饰符来评估它,如下所示:
$find="start (.*) end";
$replace='"foo $1 bar"';
$var = "start middle end";
$var =~ s/$find/$replace/ee;
print "var: $var\n";
Run Code Online (Sandbox Code Playgroud)
要查看为什么需要""和double/e,请在此处查看double eval的效果:
$ perl
$foo = "middle";
$replace='"foo $foo bar"';
print eval('$replace'), "\n";
print eval(eval('$replace')), "\n";
__END__
"foo $foo bar"
foo middle bar
Run Code Online (Sandbox Code Playgroud)
Ken*_*ric 12
Deparse告诉我们这是正在执行的内容:
$find = 'start (.*) end';
$replace = "foo \cA bar";
$var = 'start middle end';
$var =~ s/$find/$replace/;
Run Code Online (Sandbox Code Playgroud)
然而,
/$find/foo \1 bar/
Run Code Online (Sandbox Code Playgroud)
被解释为:
$var =~ s/$find/foo $1 bar/;
Run Code Online (Sandbox Code Playgroud)
不幸的是,似乎没有简单的方法可以做到这一点.
你可以用字符串eval来做,但这很危险.
对我有用的最理智的解决方案是:
$find = "start (.*) end";
$replace = 'foo \1 bar';
$var = "start middle end";
sub repl {
my $find = shift;
my $replace = shift;
my $var = shift;
# Capture first
my @items = ( $var =~ $find );
$var =~ s/$find/$replace/;
for( reverse 0 .. $#items ){
my $n = $_ + 1;
# Many More Rules can go here, ie: \g matchers and \{ }
$var =~ s/\\$n/${items[$_]}/g ;
$var =~ s/\$$n/${items[$_]}/g ;
}
return $var;
}
print repl $find, $replace, $var;
Run Code Online (Sandbox Code Playgroud)
正如我在答案中所说,我出于某种原因避免了逃避.
$find="start (.*) end";
$replace='do{ print "I am a dirty little hacker" while 1; "foo $1 bar" }';
$var = "start middle end";
$var =~ s/$find/$replace/ee;
print "var: $var\n";
Run Code Online (Sandbox Code Playgroud)
这段代码完全符合你的想法.
如果您的替换字符串在Web应用程序中,您只需打开任意代码执行的大门.
做得好.
此外,由于这个原因,它不会与打开的污点一起使用.
$find="start (.*) end";
$replace='"' . $ARGV[0] . '"';
$var = "start middle end";
$var =~ s/$find/$replace/ee;
print "var: $var\n"
$ perl /tmp/re.pl 'foo $1 bar'
var: foo middle bar
$ perl -T /tmp/re.pl 'foo $1 bar'
Insecure dependency in eval while running with -T switch at /tmp/re.pl line 10.
Run Code Online (Sandbox Code Playgroud)
然而,更谨慎的技术是理智,安全,安全,并且不会失败.(请放心,它发出的字符串仍然受到污染,因此您不会失去任何安全性.)
# perl -de 0
$match="hi(.*)"
$sub='$1'
$res="hi1234"
$res =~ s/$match/$sub/gee
p $res
1234
Run Code Online (Sandbox Code Playgroud)
但要小心.这会导致eval出现两层e,在正则表达式的末尾各出一层:
正如其他人所建议的,您可以使用以下内容:
my $find = 'start (.*) end';
my $replace = 'foo $1 bar'; # 'foo \1 bar' is an error.
my $var = "start middle end";
$var =~ s/$find/$replace/ee;
Run Code Online (Sandbox Code Playgroud)
以上是以下各项的缩写:
my $find = 'start (.*) end';
my $replace = 'foo $1 bar';
my $var = "start middle end";
$var =~ s/$find/ eval($replace) /e;
Run Code Online (Sandbox Code Playgroud)
我不喜欢第二个,因为它不会隐藏使用的事实eval(EXPR)。但是,上述两个均会出现静音错误,因此以下方法会更好:
my $find = 'start (.*) end';
my $replace = 'foo $1 bar';
my $var = "start middle end";
$var =~ s/$find/ my $r = eval($replace); die $@ if $@; $r /e;
Run Code Online (Sandbox Code Playgroud)
但是如您所见,以上所有内容都允许执行任意Perl代码。以下内容将更加安全:
use String::Substitution qw( sub_modify );
my $find = 'start (.*) end';
my $replace = 'foo $1 bar';
my $var = "start middle end";
sub_modify($var, $find, $replace);
Run Code Online (Sandbox Code Playgroud)