Erstens, das Ersatzteil eines s/.../.../
Betrieb ist nicht ein regulärer Ausdruck; Es funktioniert wie eine Zeichenfolge in doppelten Anführungszeichen.
Es gibt ein paar Probleme mit Ihrem Code.
Ihre exit 1;
Aussage erscheint in der Mitte des Haupt-Code, nicht in dem Fehlerblock. Sie wollen wahrscheinlich:
if (@ARGV != 2) {
print STDERR "Usage: ./filter.pl FROMSTRING TOSTRING\n";
exit 1;
}
Sie verpassen eine g
Flag, wenn Sie mehrere Substitutionen passieren in der gleichen Linie wollen:
$inLine =~ s/$FROM/$TO/g;
Es gibt keine Notwendigkeit zu predeclare $inLine
; Es wird nur in einem Block verwendet.
- Es ist auch nicht notwendig, eine Zeile in
$_
zu lesen, nur um es in $inLine
zu kopieren.
- Es ist üblich,
$names_like_this
für Variablen und Funktionen zu verwenden, nicht $namesLikeThis
.
- Sie können
$0
verwenden, anstatt den Programmnamen in der Fehlermeldung fest zu codieren.
exit 0;
ist am Ende redundant.
Hier finden Sie näher an, wie ich es schreiben würde:
#!/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;
}
Das heißt, keines dieser Adressen Ihr zweites Beispiel mit '$2$1'
als Ersatz. Der obige Code wird nicht tun, was Sie wollen, weil $to
eine einfache Zeichenfolge ist. Perl wird nicht nach Objekten wie $1
suchen und sie ersetzen. Wenn Sie "foo $bar baz"
in Ihren Code schreiben, bedeutet das dasselbe wie 'foo ' . $bar . ' baz'
, aber dies gilt nur für CodeZeug, das buchstäblich in Ihrem Quellcode erscheint. Der Inhalt von $bar
wird zur Laufzeit nicht erneut gescannt, um z. \n
oder $quux
. Dies gilt auch für $1
und Freunde, die nur normale Variablen sind.
So wie erhalten Sie '$2$1'
zu arbeiten?
Eine Möglichkeit ist Kampf mit eval
, aber ich mag es nicht, weil, na ja, es eval
ist: Wenn Sie nicht sehr vorsichtig sind, wäre es jemand erlauben, beliebigen Code auszuführen, indem Sie den richtigen Ersatz „String übergeben ".
Doing it ohne eval
ist möglich und sogar einfach mit z.B. 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
Werke wie die JavaScript-String#replace
, dass es spezielle $
Sequenzen erweitert.
es von Hand zu tun, ist auch möglich, aber etwas ärgerlich, weil man im Grunde $to
als Vorlage zu behandeln hat, und erweitern Sie alle $
Sequenzen von Hand (zB durch eine andere regex Substitution verwenden):
# 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;
(Dies tut Umsetzung nicht verspannten Gruppen wie ${1}
, ${2}
usw. Diese sind für den Leser als Übung.)
Dieser Code ausreichend ärgerlich ist, zu schreiben (und sehen), dass ich viel lieber ein Modul wie Data::Munge
für th mit ist eine Sache.
Hinweis - kann 'while (my $ inline =) {...}'. Also, 'my ($ from, $ to) = @ARGV;' –
zdim
Oder 's/$ from/$ to/r während;' mit '/ r' modifier [from 5.14] (http: // perldoc. perl.org/perl5140delta.html) –
zdim