I have been using the Perl command line with a -ne
option for years, largely to process text files in ways that sed can't. Example:
cat in.txt | perl -ne "s/abc/def/; s/fgh/hij/; print;" > out.txt
I have no idea where I learned this, and have only today read perlrun and found there are other forms (perl -pe
for example).
What else should I know about perl -ne
?
I often use
sed
orawk
but I really like thisperl
matching pattern killer feature:perl -ne 'CODE'
is equivalent to the programperl -ane 'CODE'
andperl -F/PATTERN/ -ane
are also good idioms to know about. They are equivalent toand
Example: advanced grep:
A particularly clever example that uses mismatched braces is here.
You can specify more than one -e clause. Sometimes I have a command line that starts growing as I refine a search / extract / mangulation operation. if you mistype something, you will get a "line number" telling you which -e has the error.
Of course, some might argue that if you have more than one or two -e clauses, maybe you should put whatever it is into a script, but some stuff really is just throw away, so why bother.
Presumably you would do something less trivial than grep / egrep into 3 files :-)
I like to think of
perl -n
as picking out specific bits of the input andperl -p
asmap
for all lines of the input.As you've observed, it's possible to get the effect of
-p
with-n
, and we can emulate the other way around:Skipping lines with
next
would seem more natural, but-p
wraps code inBy design,
next
runscontinue
blocks:The
-l
switch has two handy effects:-n
and-p
, automaticallychomp
each input record.$\
so everyprint
implicitly adds a terminator.For example, to grab the first 10 UDP ports mentioned in
/etc/services
you mightbut oops:
Better:
Remember that
-n
and-p
can be in the shebang line too, so to save the above oneliner as a script:The
-i
option lets you do the changes inline:or save a backup:
There is one important thing to know about
perl -ne
andperl -pe
scripts: they implicitly use<>
."Why is that important?" you might ask.
The magic
<>
operator uses the 2 arg form of open. If you recall, 2 arg open includes the specification of mode with the filename in one argument. An old style call toopen FILE, $foo
is vulnerable to manipulation of the file mode. A particularly interesting mode in this context is|
--you open a handle to a pipe to a process you execute.You might be thinking "Big deal!", but it is.
script *
.|rm -rf /
.What happens?
*
and we getscript file_1 file_2 '|rm -rf /' file_4
file_1
andfile_2
.rm -rf /
.file_4
no longer exists, so we can't open it.Of course, the possibilities are endless.
You can read more discussion of this issue at Perlmonks.
The moral of the story: be careful with the
<>
operator.FWIW, I just confirmed that this is still an issue with perl 5.10.0.