Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl query using -pie

Tags:

perl

This works:

perl -pi -e 's/abc/cba/g' hellofile

But this does not:

perl -pie 's/cba/abc/g' hellofile

In other words -pi -e works but -pie does not. Why?

like image 973
Ankur Agarwal Avatar asked Oct 28 '11 23:10

Ankur Agarwal


3 Answers

perl already tells you why :) Try-It-To-See

$ perl -pie " s/abc/cba/g " NUL
Can't open perl script " s/abc/cba/g ": No such file or directory

If you use B::Deparse you can see how perl compiles your code

$ perl -MO=Deparse -pi -e " s/abc/cba/g " NUL
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/abc/cba/g;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK

If you lookup $^I in perlvar you can learn about the -i switch :)

$ perldoc -v "$^I"

    $INPLACE_EDIT
    $^I     The current value of the inplace-edit extension. Use "undef" to
            disable inplace editing.

            Mnemonic: value of -i switch.

Now if we revisit the first part, add an extra -e, then add Deparse, the -i switch is explained

$ perl -pie -e " s/abc/cba/g " NUL
Can't do inplace edit: NUL is not a regular file.

$ perl -MO=Deparse -pie -e " s/abc/cba/g " NUL
BEGIN { $^I = "e"; }
LINE: while (defined($_ = <ARGV>)) {
    s/abc/cba/g;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK

Could it really be that e in -pie is taken as extension? I guess so

$ perl -MO=Deparse -pilogicus -e " s/abc/cba/g " NUL
BEGIN { $^I = "logicus"; }
LINE: while (defined($_ = <ARGV>)) {
    s/abc/cba/g;
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK

When in doubt, Deparse or Deparse,-p

like image 74
logicus Avatar answered Nov 09 '22 21:11

logicus


The -i flag takes an optional argument (which, if present, must be immediately after it, not in a separate command-line argument) that specifies the suffix to append to the name of the input file for the purposes of creating a backup. Writing perl -pie 's/cba/abc/g' hellofile causes the e to be taken as this suffix, and as the e isn't interpreted as the normal -e option, Perl tries to run the script located in s/cba/abc/g, which probably doesn't exist.

like image 25
jwodder Avatar answered Nov 09 '22 21:11

jwodder


Because -i takes an optional extension for backup files, e.g. -i.bak, and therefore additional flags cannot follow directly after -i.

From perldoc perlrun

-i[extension]

specifies that files processed by the <> construct are to be edited in-place. It does this by renaming the input file, opening the output file by the original name, and selecting that output file as the default for print() statements. The extension, if supplied, is used to modify the name of the old file to make a backup copy, following these rules:

If no extension is supplied, no backup is made and the current file is overwritten.

If the extension doesn't contain a * , then it is appended to the end of the current filename as a suffix. If the extension does contain one or more * characters, then each * is replaced with the current filename. In Perl terms, you could think of this as:

like image 10
TLP Avatar answered Nov 09 '22 23:11

TLP