首先,一个操作s/.../.../
的替换部分不是正则表达式;它像双引号字符串一样工作。
有几个与你的代码的问题。
你exit 1;
语句出现在主代码的中间,而不是在错误块。你可能想:
if (@ARGV != 2) {
print STDERR "Usage: ./filter.pl FROMSTRING TOSTRING\n";
exit 1;
}
你错过,如果你想多换人在同一行发生一g
标志:
$inLine =~ s/$FROM/$TO/g;
有没有必要预先声明$inLine
;它只在一个块中使用。
- 但也没有必要读行成
$_
只是将其复制到$inLine
。
- 它通常使用
$names_like_this
变量和函数,而不是$namesLikeThis
。
- 可以使用
$0
,而不是在错误信息硬编码的程序名。
exit 0;
是在端冗余。
以下是更接近我怎么会写:
#!/usr/bin/perl
use strict;
use warnings;
if (@ARGV != 2) {
die "Usage: $0 FROMSTRING TOSTRING\n";
}
my ($from, $to) = @ARGV;
while (my $line = readline STDIN) {
$line =~ s/$from/$to/g;
print $line;
}
这就是说,这些都不满足您与'$2$1'
作为替换第二个例子。上面的代码不会做你想要的,因为$to
是一个纯字符串。 Perl不会扫描它来寻找类似$1
的东西并替换它们。
当您在代码中编写"foo $bar baz"
时,它与'foo ' . $bar . ' baz'
意思相同,但这仅适用于代码,即东西,字面上出现在您的源代码。在运行时不会重新扫描$bar
的内容以扩展例如\n
或$quux
。这也适用于$1
和朋友,这只是普通变量。
那么你如何得到'$2$1'
工作?
一种方法是混淆eval
,但我不喜欢它,因为它是eval
:如果你不是很小心,它会允许某人通过传递正确的替换字符串来执行任意代码“string ”。
不用eval
就可以做到这一点,甚至可以使用例如Data::Munge::replace
:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Munge qw(replace);
if (@ARGV != 2) {
die "Usage: $0 FROMSTRING TOSTRING\n";
}
my ($from, $to) = @ARGV;
while (my $line = readline STDIN) {
print replace($line, $from, $to, 'g');
}
replace
作品像JavaScript的String#replace
,从而扩展特殊$
序列。
做手工也是可能的,但有点恼人,因为你基本上要像对待$to
为模板,扩大手工所有$
序列(通过其他正则表达式替换EG):
# untested
$line =~ s{$from}{
my @start = @-;
my @stop = @+;
(my $r = $to) =~ s{\$([0-9]+|\$)}{
$1 eq '$'
? '$'
: substr($from, $start[$1], $stop[$1] - $start[$1])
}eg;
$r
}eg;
(这确实没有实现如${1}
,${2}
等。这些都是作为练习留给读者桁组)。
此代码是足够烦人写(看看),我更喜欢使用一个模块一样Data::Munge
的日是某种事情。
注 - 可以做'while(my $ inline =){...}'。另外,'我的($ from,$ to)= @ARGV;' –
zdim
或'print s/$ from/$ to/r;''用'/ r'修饰符[来自5.14](http:// perldoc。 perl.org/perl5140delta.html) –
zdim