问题
I would like to move several one liners into a single script.
For example:
perl -i.bak -pE "s/String_ABC/String_XYZ/g" Cities.Txt
perl -i.bak -pE "s/Manhattan/New_England/g" Cities.Txt
Above works well for me but at the expense of two disk I/O operations.
I would like to move the aforementioned logic into a single script so that all substitutions are effectuated with the file opened and edited only once.
EDIT1: Based on your recommendations, I wrote this snippet in a script which when invoked from a windows batch file simply hangs:
#!/usr/bin/perl -i.bak -p Cities.Txt
use strict;
use warnings;
while( <> ){
s/String_ABC/String_XYZ/g;
s/Manhattan/New_England/g;
print;
}
EDIT2: OK, so here is how I implemented your recommendation. Works like a charm!
Batch file:
perl -i.bal MyScript.pl Cities.Txt
MyScript.pl
#!/usr/bin/perl
use strict;
use warnings;
while( <> ){
s/String_ABC/String_XYZ/g;
s/Manhattan/New_England/g;
print;
}
Thanks a lot to everyone that contributed.
回答1:
The -p
wraps the argument to -E
with:
while( <> ) {
# argument to -E
print;
}
So, take all the arguments to -E
and put them in the while
:
while( <> ) {
s/String_ABC/String_XYZ/g;
s/Manhattan/New_England/g;
print;
}
The -i
sets the $^I
variable, which turns on some special magic handling ARGV
:
$^I = "bak";
The -E
turns on the new features for that versions of Perl. You can do that by just specifying the version:
use v5.10;
However, you don't use anything loaded with that, at least in what you've shown us.
If you want to see everything a one-liner does, put a -MO=Deparse in there:
% perl -MO=Deparse -i.bak -pE "s/Manhattan/New_England/g" Cities.Txt
BEGIN { $^I = ".bak"; }
BEGIN {
$^H{'feature_unicode'} = q(1);
$^H{'feature_say'} = q(1);
$^H{'feature_state'} = q(1);
$^H{'feature_switch'} = q(1);
}
LINE: while (defined($_ = <ARGV>)) {
s/Manhattan/New_England/g;
}
continue {
die "-p destination: $!\n" unless print $_;
}
-e syntax OK
回答2:
You can put arguments on the #! line. Perl will read them, even on Windows.
#!/usr/bin/perl -i.bak -p
s/String_ABC/String_XYZ/g;
s/Manhattan/New_England/g;
or you can keep it a one-liner as @ephemient said in the comments.
perl -i.bak -pE "s/String_ABC/String_XYZ/g; s/Manhattan/New_England/g" Cities.Txt
-i
+ -p
basically puts a while loop around your program. Each line comes in as $_
, your code runs, and $_
is printed out at the end. Repeat. So you can have as many statements as you want.
来源:https://stackoverflow.com/questions/11858147/how-can-i-consolidate-several-perl-one-liners-into-a-single-script