Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Uncommon* but Useful Perl Command Line Options for One-liners

by Sol-Invictus (Scribe)
on Jan 28, 2004 at 19:31 UTC ( #324749=perltutorial: print w/ replies, xml ) Need Help??

* 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'

Comment on Uncommon* but Useful Perl Command Line Options for One-liners
Select or Download Code
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 ();
    Boris
      I'm open to suggestions for a simple way to show symbols not being imported from a module :) Originally I wrote:
      use Module(fuction); (-M) and use Module(); (-m)
      but I thought newbies would get confused.

      Correct. Proof:

      $ perl -MO=Deparse -MCGI -e '' -e syntax OK use CGI; (); $ perl -MO=Deparse -mCGI -e '' -e syntax OK use CGI (); ();

      ----
      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

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).

      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
        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.
Re: Uncommon but Useful Perl Command Line Options
by Not_a_Number (Parson) 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

      fair points - note however I wrote and tested this on a Mac :).

        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

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

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

      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 :)
      -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.

        These could be construed as a bug. (sic)
        ..or as devious tools to use for strict-safe obfuscation. Mu-ha-ha-ha-ha. ;)

        thor

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 $\.

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:
    switcheffect
    -0\0 record separator
    -00paragraph mode
    -000paragraph mode
    -0000paragraph mode
    -00000\0 record separator
    -000000paragraph mode
    -0000000paragraph mode
    -00000000paragraph mode
    -000000000\0 record separator
    -0000000000paragraph 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.

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.

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.

      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


        :o very nice i found it very useful! Thanks! :D

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perltutorial [id://324749]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (7)
As of 2014-12-27 02:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (176 votes), past polls