首先,一個操作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