Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

-i switch behaviour

by fireartist (Chaplain)
on Jun 18, 2004 at 13:25 UTC ( [id://367934]=perlquestion: print w/replies, xml ) Need Help??

fireartist has asked for the wisdom of the Perl Monks concerning the following question:

I'm been experimenting with the command line switch -i.
I was confused with results at first, but I think I'm starting to figure it out.

I have a file "testfile" that contains the text "testdata".
When I run ls testfile | perl -lpi -e 's/e/*/' I get the output "t*stfil*" and the file contents are unchanged.
However, if I run ls testfile | xargs perl -lpi -e 's/e/*/' There is no output to STDOUT, and the contents of the textfile are changed as expected, now reading "t*stdata".

It took me a while to figure out what was happening, but it seems that files are only edited in place when the filenames are passed as arguments, not as STDIN.
This was confirmed when I found merlyn's post xargs functionality for inplace editing which uses find ... -print | perl -pi.bak -e 'BEGIN { chomp(@ARGV = <STDIN>) } s/foo/bar/g' However, perlrun -i "specifies that files processed by the <> construct are to be edited in-place"
The code explaination also reads
LINE: while (<>) { ... }
I thought that meant it processes <STDIN>, not @ARGV, am I reading perlrun wrong or should the code example read ...?
LINE: while (@ARGV) { ... }

Replies are listed 'Best First'.
Re: -i switch behaviour
by thospel (Hermit) on Jun 18, 2004 at 13:48 UTC
    You seem to be confusing the list of files with the filecontents.

    -i replaces the files given as @ARGV inplace, and <> is an iterator over the contents of each of these files. If @ARGV is empty, STDIN is used to supply the contents, not to supply the list of filename(s). So your -e code is applied to the list of files itself, not to the contents of these files. And it can't then use the result to do an update, since there actually is no file that that the list is the contest of.

    That's of course the case in general. There is no reason to think STDIN is associated with a file (in your case it's a pipe), so a rewrite of that "file" makes no sense. And that's also what makes xargs so nice. It allows you to convert an inputstream to a list of arguments.

      Yeah, I know I'm confused!
      If @ARGV is empty, STDIN is used to supply the contents, not to supply the list of filename(s)
      That's a good explanation!
      I think where I went wrong was initially experimenting with the -n and -p switches in the form
      find ... | perl -ne 'do something'
      and then when I added -i I though it would automatically edit the files the same way
      find ... | perl -nie 'do something'
      and I didn't know why I was having to use
      find ... | xargs perl -nie 'do something'
      to get my desired results.
      Thanks for your help.
Re: -i switch behaviour
by pbeckingham (Parson) on Jun 18, 2004 at 13:27 UTC

    If you pipe the output of ls into perl, you are really just giving it a string containing file names. You need to change that to:

    perl -lpi -e 's/e/*/' testfile
    In order to give perl the opportunity to scan @ARGV and then read the file contents.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://367934]
Approved by Limbic~Region
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-04-25 17:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found