|
* if you think that -e, -p, -n,-l, -0,-a, -F & -M don't seem that uncommon to you, then this probably isn't the tutorial for you.
Perl has a bewildering array of choices, some you probably already know -w(warnings), -T(tainting) and -i (inline editing), but the rest?:
(from perl --help)
Usage: perl [switches] [--] [program file] [arguments]
-0[octal] specify record separator (\0, if no argument)
-a autosplit mode with -n or -p (splits $_ into @F)
-C enable native wide character system interfaces
-c check syntax only (runs BEGIN and CHECK blocks)
-d[:debugger] run program under debugger
-D[number/list] set debugging flags (argument is a bit mask or alphabets)
-e 'command' one line of program (several -e's allowed, omit programfile)
-F/pattern/ split() pattern for -a switch (//'s are optional)
-i[extension] edit <> files in place (makes backup if extension supplied)
-Idirectory specify @INC/#include directory (several -I's allowed)
-l[octal] enable line ending processing, specifies line terminator
-[mM][-]module execute `use/no module...' before executing program
-n assume 'while (<>) { ... }' loop around program
-p assume loop like -n but print line also, like sed
-P run program through C preprocessor before compilation
-s enable rudimentary parsing for switches after programfile
-S look for programfile using PATH environment variable
-T enable tainting checks
-t enable tainting warnings
-u dump core after parsing program
-U allow unsafe operations
-v print version, subversion (includes VERY IMPORTANT perl info)
-V[:variable] print configuration summary (or a single Config.pm variable)
-w enable many useful warnings (RECOMMENDED)
-W enable all warnings
-X disable all warnings
-x[directory] strip off text before #!perl line and perhaps cd to directory
Here we're going to be looking at options we can use with command line scripts, so those opts whose usage falls outside this spec, are beyond the scope of this document and will not be presented for your delectation, though for the curious a full description of what each and every option does can be found in perlrun.
Options covered herein therefor and whencebefore:
-e, -p, -n,-l, -0,-a, -F, -M
First up: -e (execute)
Without this none of our examples will work, use it to run script input from the command line, aka one-liners:
perl -e '$date=localtime(time); print $date;'
you could pass a 200 line script like this - though you might find it a pain to write all on one line. With '-e' beware of quoting though - try running this :
perl -e "$date=localtime(time); print $date;"
Windows (using command.com) prefers double quotes, but the above won't work in on *nix, where shells prefer single quotes, and is the style used for the rest of this tutorial. MacOS users (>=OS9) can get more info about command line switches and using them in MacPerl here.
Next up: -l (line endings)
You probably noticed after running the previous example, that your shell prompt was rammed against the date output from the script, annoying when that happens isn't it. We could of course slap a new line in there:
perl -e '$date=localtime(time); print $date,"\n";'
but all that quoting gets you carpal tunnel syndrome fast, instead try this:
perl -l -e '$date=localtime(time); print $date;'
-l is used with -n and -p and has a dual nature - on input it behaves like chomp(), automatically removing newline characters, while on output, as we've seen, it becomes the anti-chomp, adding newlines.
caveat: it works it's magic only on print()
Next up: -n (looping)
this option is shorthand for:
while(<>) { }
(Puzzled by this code example?: the empty diamond operator '<>' means it expects input from outside the script).
Try passing a text file to this one-liner and see how many words have "ear"s :
perl -l -n -e 'print $1 if /(\w+ear)/' some.txt
Ok I lied, there is a difference between the longhand perl while (<>) { } statement and -n: you can't use next or last to exit the loop - however you can use BEGIN{ } and END { } blocks to get pre and post loop code, run a text file containing some numbers through this baby:
perl -l -n -e 'BEGIN{$sum=0;} $sum=$sum+ $1 if /(\d+)/;print $1; END {
+print "Total: ",$sum}'
Next up: -p (looping plus)
in longhand it looks like this:
while(<>) { print ; }
(Puzzled by this code example?: the empty print statement means it prints the $_ variable).
Run a text through this script and tell it like it is:
perl -l -p -e 's/Microsoft/Micro\$\$\$oft/g' some.txt
Remember the same caveat applies to -p as -n - you can't break out of the loop with next or last. You can use BEGIN{ } and END { } blocks however:
perl -l -n -e 'BEGIN{open (OUT,/path/to/file || die } print if /^.*\w
+{2,}.*$/gm; END {close (OUT); }'
Next up: -a (split)
in longhand:
split;
(Puzzled by this code example?: this means the same as @_=split (' ',$_).)
The resulting data is put into an array called @F, needs to be used with either -n or -p. Run a text or string through this script and print out the 5th word of each line:
perl -l -a -n -e 'print $F[5]' some.txt
If you need to split data on something other than whitespace use -Fpatt (split pattern):
perl -l -a -F: -n -e 'print $F[0]' /etc/passwd
Next up: -0 (record separator)
Note that's a ZERO not the letter 'O'. Using this is like messing with $/ in a script, so if you're on an old style MacOS box and you want to edit a text file created on Unix:
perl -012 -e ...
You can set any character to be the record separator by giving its octal value to -0. Caveat programmer - by assigning a value to -0 it will logically also affect -l.
There are two special octal codes which are used for paragraph mode and slurp mode respectively:
-00 ( paragraph mode) -0777 (slurp mode)
(Puzzled by this code topic?: when perl reads in a file it breaks the data into lines by looking for a newline (\n) character by default. This behaviour can be changed by putting a new value into the $/ variable, notably $/="" tells perl to see two or more consecutive empty lines as a single empty line allowing you to read in paragraphs at a time, instead of lines. $/="undef" will allow you to read in a whole file. Like a reminder to the truth of relativity and the relativity of truth, Perl's \n doesn't have a fixed value, panning across systems it's \012 on Unix, on Windows \015\012 and pre OSX Mac \015, so dealing with files originating from other OS needs means your \n, wasn't their\n.)
Finally: -M (& -m) (modules)
The difference is not so huge between these two opts
-M like use Module;
-m is like use Module();
(Puzzled by this code topic?: when you use a module you have two choices:
(a) to pull the functions from the module into your script so you can call them as if they were in your script:
use Wallace(gromit);
$saveTheDay=gromit(data);
b) leave them where they are and call them by their full name:
$saveTheDay=Wallace::gromit(data);
)
Useful for quick checking a module version
perl -l -MNet::Telnet -e'print $Net::Telnet::VERSION'
or grabbing a web page
perl -MLWP::Simple -e '$content = get("http://www.perlmonks.org/")
+;print $content'
Re: Uncommon but Useful Perl Command Line Options by borisz (Canon) on Jan 28, 2004 at 19:48 UTC |
Very nice,
only the -m is like use Module::module;
looks wrong to me.
I think it is like use Module ();
| [reply] [d/l] |
|
| [reply] [d/l] |
|
| [reply] [d/l] [select] |
Re: Uncommon but Useful Perl Command Line Options by ysth (Canon) on Jan 28, 2004 at 20:31 UTC |
I'd take out the part from perldoc perl and replace it with the output from perl --help. Seems perl.pod has gotten out of date. In particular, I notice the -C switch (which did one thing <5.8.1 and something very different >=5.8.1) is missing.
Output from 5.8.3:
Usage: ./perl [switches] [--] [programfile] [arguments]
-0[octal] specify record separator (\0, if no argument)
-a autosplit mode with -n or -p (splits $_ into @F)
-C[number/list] enables the listed Unicode features
-c check syntax only (runs BEGIN and CHECK blocks)
-d[:debugger] run program under debugger
-D[number/list] set debugging flags (argument is a bit mask or alpha
+bets)
-e program one line of program (several -e's allowed, omit prog
+ramfile)
-F/pattern/ split() pattern for -a switch (//'s are optional)
-i[extension] edit <> files in place (makes backup if extension su
+pplied)
-Idirectory specify @INC/#include directory (several -I's allowe
+d)
-l[octal] enable line ending processing, specifies line termin
+ator
-[mM][-]module execute `use/no module...' before executing program
-n assume 'while (<>) { ... }' loop around program
-p assume loop like -n but print line also, like sed
-P run program through C preprocessor before compilatio
+n
-s enable rudimentary parsing for switches after progra
+mfile
-S look for programfile using PATH environment variable
-t enable tainting warnings
-T enable tainting checks
-u dump core after parsing program
-U allow unsafe operations
-v print version, subversion (includes VERY IMPORTANT p
+erl info)
-V[:variable] print configuration summary (or a single Config.pm v
+ariable)
-w enable many useful warnings (RECOMMENDED)
-W enable all warnings
-x[directory] strip off text before #!perl line and perhaps cd to
+directory
-X disable all warnings
Also, I have trouble with your "Uncommon". Seems to me you cover only the most common switches (other than -w). | [reply] [d/l] |
|
ok will edit the text to point to perl --help, as to
uncommon, I was aiming for people who have little or no experience of using command line opts (except for -w,-i,-T) I will make that clearer at the outset
| [reply] |
|
You seem to have picked the ones most useful for one-liners (but not only for one-liners, of course). Perhaps you could work that into the title somehow? Or maybe that would scare people off.
| [reply] |
|
Re: Uncommon but Useful Perl Command Line Options by Not_a_Number (Vicar) on Jan 28, 2004 at 20:36 UTC |
Sol-Invictus++!
However, as this is posted as a tutorial (and should consequently attract a lot of not-so-experienced PMs), and since perl is cross-platform, I suggest you either:
1) Add "(for *nix users only)" to your title;
2) Include a preamble about different quoting systems for one-liners on different OSs; or:
3) Point non_*nix users to perlfaq3 "Why don't perl one-liners work on my DOS/Mac/VMS system?"
dave
| [reply] |
|
fair points - note however I wrote and tested this on a Mac :).
| [reply] |
|
Okay. But your examples don't work on Windoze.
Basic advice to Win users:
Change " to ' # Double quotes to single quotes
dave
Update - Ooops: Of course, I wrote exactly the opposite of what I meant:
Change ' to " # Single quotes to double quotes
dave
| [reply] [d/l] [select] |
|
Re: Uncommon but Useful Perl Command Line Options by hardburn (Abbot) on Jan 28, 2004 at 22:01 UTC |
'-l' has a dual nature - on input it behaves like chomp(), automatically removing newline characters, while on output, as we've seen, it becomes the anti-chomp, adding newlines.
. . .
-0 . . . Using this is like messing with $/ in a script . . .
For completeness, I would mention that '-l' is implemented by messing with $\ and $/:
$ perl -MO=Deparse -le ''
-e syntax OK
BEGIN { $/ = "\n"; $\ = "\n"; }
();
Also, you can specifiy a different character (in octal) on the command line for -l to use for $\ (output records):
$ perl -MO=Deparse -l001 -e ''
-e syntax OK
BEGIN { $/ = "\n"; $\ = "\001"; }
();
-0 can also take an octal number, but this time it sets $/ (input records):
$ perl -MO=Deparse -0001 -e ''
-e syntax OK
BEGIN { $/ = "\001"; $\ = undef; }
();
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
: () { :|:& };:
Note: All code is untested, unless otherwise stated
| [reply] [d/l] [select] |
Re: Uncommon* but Useful Perl Command Line Options by Abigail-II (Bishop) on Jan 29, 2004 at 00:20 UTC |
you could pass a 200 line script like this -
though you might find it a pain to write all on one line.
So, write it on multiple lines. -e may be repeated:
$ perl -wl -e 'print "This is line 1";' \
-e 'print "This is line 2";' \
-e 'print "This is line 3";' \
-e 'print "This is line 4";' \
-e 'print "This is line 5";'
works like a charm.
-p (looping plus)
in longhand it looks like this:
while(<>) { print ; }
Actually, it's a bit more subtle than that, as can be shown by
using the deparser:
$ perl -MO=Deparse -pe '1'
LINE: while (defined($_ = <ARGV>)) {
'???';
}
continue {
print $_;
}
-e syntax OK
The print is done in a continue block, so it will print even if you
use next in the supplied code. Note also the label.
-a (split)
in longhand:
split;
Well, that should be: @F = split;, but it should be
noteworthy that -a only works in combination with
-n or -t.
perl -01512 -e
This is what I get when I run it:
$ perl -01512 -e 1
Unrecognized switch: -2 (-h will show valid options).
$
You can only use -0 to set $/ to a one character string -
not to set it to \r\n.
Abigail
| [reply] [d/l] [select] |
|
erratum and tips noted, but
- the tut does say that -a outputs to @F
- entering a 200 line script on the command line with continuation lines - I'd prefer to write that as a .pl file :)
| [reply] |
|
-a only works in combination with -n or -t
I assume this is a typo and Abigail meant -n or -p.
Actually, even without -n or -p, the -a switch does have the very minor effect of creating @F, so that referring to it won't get you a Name "main::F" used only once: possible typo warning. (And *F{ARRAY} will give a reference to @F even if no @F is mentioned anywhere, instead of the usual undef.) These could be construed as a bug.
| [reply] [d/l] |
|
These could be construed as a bug. (sic)
..or as devious tools to use for strict-safe obfuscation. Mu-ha-ha-ha-ha. ;)
| [reply] |
Re: Uncommon* but Useful Perl Command Line Options (for one-liners) by ysth (Canon) on Jan 29, 2004 at 00:49 UTC |
'-l' has a dual nature - on input it behaves like chomp(), automatically removing newline characters, while on output, as we've seen, it becomes the anti-chomp, adding newlines.
This needs more explication. -l's effect on input and output are not as parallel as this would imply.
-l's effect on input only applies to the LINE loop generated by -n or -p (by adding a chomp at the beginning). If -n and -p aren't specified, no input is changed.
-l's effect on output applies to all print (but not printf) statements, however situate (by virtue of setting $\).
Update: said $/ meant $\.
| [reply] |
Re: Uncommon* but Useful Perl Command Line Options (for one-liners) by ysth (Canon) on Jan 29, 2004 at 01:51 UTC |
so dealing with files originating from other OS needs the ability to change the value of \n
I would say "to change the value of $/". -0 certainly doesn't change \n.
There are also some funky details about how -0 works.
First of all, -0[octal] is limited to 3 following octal digits. Anything beyond that is interpreted as a new bundled switch (e.g. -07770 is equivalent to -0777 -0 (which is equivalent to just -0)).
-0 with no following octal digits will set $/ to "\0", the null character. As you say, -00 does paragraph mode ($/ = "") instead. This applies to -000 and -0000 also; as above, -00000 etc is interpreted as two separate switches where the first is meaningless, creating the pleasant cycle:
| switch | effect
|
|---|
| -0 | \0 record separator
| | -00 | paragraph mode
| | -000 | paragraph mode
| | -0000 | paragraph mode
| | -00000 | \0 record separator
| | -000000 | paragraph mode
| | -0000000 | paragraph mode
| | -00000000 | paragraph mode
| | -000000000 | \0 record separator
| | -0000000000 | paragraph mode |
Not just -0777, but any attempt to specify an octal character greater than 0377 (255 decimal), will trigger
slurp mode.
And starting with 5.8.1, -0 will allow hex characters to be specified like -0x1ff (but you can't bundle it with other switches like -0x1ffw; for backward compatibility, that is interpreted as -0 -x1ffw instead of -0x1ff -w (see perlrun for details on the -x switch)). Any number of hexidecimal digits are permitted, but only the low 32-bits are used. This allows specifying any unicode character as the record separator. Paragraph mode or slurp mode cannot be specified with -0x; -0x0 sets $/ to "\0", not "", -0x1ff (the "equivalent" of -0777) sets $/ to "\x{1ff}", not undef.
-0x actually allows an extra "x" or "0x" after the first one (e.g. -0x0x0d or -0xx0); this can be construed as a bug.
| [reply] |
Re: Uncommon* but Useful Perl Command Line Options (for one-liners) by ysth (Canon) on Jan 29, 2004 at 02:13 UTC |
As I alluded to, with 5.8.1,
-C enable native wide character system interfaces
became
-C[number/list] enables the listed Unicode features
and it would be better, IMO, to show the newer --help.
From the perldelta for 5.8.1:
The -C Switch Has Been Repurposed
The -C switch has changed in an incompatible way. The old semantics
of this switch only made sense in Win32 and only in the "use utf8"
universe in 5.6.x releases, and do not make sense for the Unicode
implementation in 5.8.0. Since this switch could not have been used
by anyone, it has been repurposed. The behavior that this switch
enabled in 5.6.x releases may be supported in a transparent,
data-dependent fashion in a future release.
For the new life of this switch, see perl581delta "UTF-8 no longer default under
UTF-8 locales", and perlrun/-C.
| [reply] [d/l] [select] |
Re: Uncommon* but Useful Perl Command Line Options for One-liners by sfink (Deacon) on Jan 29, 2004 at 17:50 UTC |
Ok I lied, there is a difference between the longhand perl while (<>) { } statement and -n: you can't use next or last to exit the loop - however you can use BEGIN{ } and END { } blocks to get pre and post loop code, run a text file containing some numbers through this baby:
perl -l -n -e 'BEGIN{$sum=0;} $sum=$sum+ $1 if /(\d+)/;print $1; END {
+print "Total: ",$sum}'
You were right the first time. There really is no difference. Why don't next and last work for you?
echo -e "a\nb\nc" | perl -lne 'next if /b/; print'
a
c
echo -e "a\nb\nc" | perl -lne 'last if /b/; print'
a
In fact, it is equivalent to
LINE: while (defined($_=<ARGV>)) { ... }
which means that you can do next LINE if you have a loop within your one-liner.
Two other comments: I use the canonical
perl -lne 'print $s += $1 if /(\d+)/'
for summing numbers. For one-liners, it's much less typing, and gives you pretty much everything you need: the total sum, and a running sum that still allows you to catch errors.
And finally, the one big missing piece in this tutorial is that it is absolutely necessary, for reasons of tradition, to at least try to make your options spell out words. So never use -alne when -lane would work.
| [reply] [d/l] [select] |
|
You were right the first time. There really is no difference. Why don't next and last work for you?
I interpreted that to mean that under -p you cant use next to skip the print, otherwise I was confused too.
---
demerphq
First they ignore you, then they laugh at you, then they fight you, then you win.
-- Gandhi
| [reply] [d/l] |
|
:o very nice i found it very useful!
Thanks! :D
| [reply] |
Back to Tutorials
|
|