Getting Started
Introduction
Perl IDEs
History
Advice
Tools
Mini-Tutorial
Tutorial
Code Snippets

Resources
Top Sites
More Tutorials
Books
Magazines
Articles
NewsLetters
Mailing Lists
NewsGroups
Forums
User Groups
Talk Shows
Blogs
Clothing

GBIC >> Perl >> Information Center Tutorials >> One Liners >> Basics

Perl Information Center Tutorials - One Liner Basics
These tutorials were written to help you get a quick, but thorough, understanding of Perl - the scope of the language as well as it's specific capabilities.

Beginners Built-In Functions     Advanced CGI Applications

One Liners
Perl allows a complete, single line script to be run from the command line. These 'one liners' can be a quick way of making changes, finding information or presenting file content.

Most Perl programmers don't use one liners and are happy to use more relaxed, readable code in standard multi-line script files. Other programmers enjoy the speed and convenience of one liners or simply enjoy the challenge of cramming as much code/logic into one line as possible.

The following three sections provide information on how to create one liners, over 75 scripts, and detailed explanation of how the scripts work.

Constructing One Liners
All one liners use Perl at the command line with the -e switch, which tells Perl that code will be supplied from the command line rather than from a file. Additional (but optional) switches, input text file names, piping and redirection (which are a function of the operating system shell) can also be used to make one liners even more versatile.

Here's the basic one liner structure. You'll see that the Hello World example (repeated here) fits this structure, with the optional file name removed.

     perl -e " " filename.txt           # code + optional file name
     perl -e "print 'Hello World!'"     # with Perl code, no file name

Many useful one liner scripts are that simple, while others are somewhat more complicated. This page walks you through the following topics, providing information you'll need to know to write a full range of one liners.

One Liner Length
Most one liners are usually no more than a standard 80 character line of text. Almost all of one liners provided on this page fall into that category.

However, a one liner can actually be fairly long. On Windows XP the maximum length of the command line is 8191 characters (2047 characters for earlier versions of Windows). So the term one liner is slightly misleading since a command line can take far more than the 80 character width of a standard display line of text.

One Liners and Windows
Unfortunately, Perl programs don't always work in Windows exactly as they do on Unix. Sometimes, a script that works on Unix won't even work on Windows.

I decided to focus this tutorial on running Perl one liners on Windows and have verified that all of the one liners scripts will run correctly on a PC. I have not verified that they will work on Unix.

For example, the Windows command line requires double quotes around the code, whereas Unix supports both single and double single quotes. This and other Windows/Unix issues are discussed in more detail below.

Using Files
The -e switch tells Perl to expect the script (in quotes), optionally followed by one or more file names. The content of the file names are fed to the one liner program, one after the other, via STDIN. A single file name, or multiple file names separated by a space are supported by Windows. Filename wildcards are supported by Unix, but not by Windows. Wildcard workarounds for Windows are discussed below.

The two approaches to entering multiple file names in Windows are shown in the following one liner examples (neither example has any Perl code in them).

     perl -e " " input.txt              # single file name
     perl -e " " input1.txt input2.txt  # multiple file names (no commas)

To read each line of the supplied filenames, just use the <> operator, as in the following examples.

     perl -e "print <>"  input.txt               # single file printed
     perl -e "print <>"  input1.txt input2.txt   # both files printed

Once all the lines of a file in the list are read, Perl continues to read lines in any additional files.

The command line content following the one liner code is available to the code via the array @ARGV, thus providing access to the individual names supplied on the command line. In the above example, the array @ARGV contains two elements, 'input1.txt' and 'input2.txt'.

Using File Wildcards
Unfortunately, using wildcards on the command line in Windows isn't supported. The problem is that Perl expects the command line to expand the wildcard list. Unix does this but Windows does not. The following example, which shows the preferred way to enter multiple file names, works in Unix but not in Windows.

     perl - e "print <>" *.txt

Fortunately there are several ways to use wildcards with Perl one liners in Windows, as shown in the following examples.

     perl -e "for (<*.txt>) {print <>}    # <> will expand wildcards
     perl -e "for (`dir /b *.txt`) {print <>}"     # backtick runs dir command
     perl -e "for (glob '*.txt') {print <>}"     # Perl glob supports wildcards
     dir /b *.txt | perl -e "print <>"       # piping feeds filenames to script

The first 3 approaches create lists of file names which are used in for loops to print the file content. The last example using the DOS piping command to send the file names to the Perl script.

Redirecting Output
When running any Perl script that prints its output to the screen you can use redirection to send the screen output to a file, as the following examples show.

     perl -e " print 'hello'" >  output.txt     # create output.txt
     perl -e " print 'hello'" >> output.txt     # append to output.txt

The > redirection symbol creates a file and fills it with the output of the Perl one liners. The >> redirection symbol opens the output file and appends the output of the of the Perl script.

Piped Inputs
When running a Perl script you may send the output of any shell command to a Perl script using the | piping command, as the following example shows.

     dir /b *.jpg | perl -e "print <>"     # prints content of *.jpg files
     type input.txt | perl -e "print <>"   # prints content of input.txt

The piping symbol | is used to send the output of a shell command to the Perl script. In this case the <> symbols read STDIN, which is where the piping input is fed to the one liner.

Multi-Script One Liners
Although one liner commands are the topic of this tutorial, the -e switch can actually be used more than once to execute multiple Perl scripts, as in the following example.

     perl -e "print 5;" -e "print 6"    # two scripts, one for each -e

This simple example will print "56", resulting from the execution of the two separate Perl scripts. Note that the semicolon is required in all Perl statements except the last one, hence the semicolon in "print 5;"

Variable values defined in a -e switch carry over to the Perl code in the next -e switch For example, the following script correctly prints the values of $a as 5.

     perl -e "$a=5;" -e "print $a"    # prints "5"

Quote Characters
The number one difference between Windows and Unix one liners is that Windows must use the double quote, whereas Unix can use single quotes. You can use single quotes for inner quotes within the code, but when interpolation is needed you'll need to use the qq// double quote operator, which is recognized by Windows.

    perl -e "$a = 'Hello World'; print qq/$a/" # prints "Hello World"
    perl -e "$a = 'Hello World'; print q/$a/" # prints "Hello World"

The first example uses the qq// double quote to ensure that $a is interpolated to print "Hello World". The second example uses the q// single quote, which does not interpolate and will print the literal characters "$a".

Remember to separate each additional code statement with a semicolon. Only the very last statement does not need a semicolon.

Perl scripts can also be written using other quoting operator delimiters. See perldoc for more details, but here's an example where the {} symbols are used in place of the // characters.

     perl -e "$a=5;print q{single quotes}.qq{double quotes $a}"   

Newline Character
A second confusion between Windows and Unix is the newline character. In Unix text lines are separated by 0D - a single character, the carriage return. In Windows, text lines are separated by 0D0A - two characters, the carrage return and line feed.

The problem for Windows users is that many Perl functions assume that a newline is a single character. For example, the Perl length function incorrectly reports 0D0A as a single character.

There's no single solution to the problem. I haven't gone through every function to see how each handles newlines, nor am I aware of a listing which provides a summary of functions/issues.

What I do have is the following summary information to help understand how Windows handles the newline (OD0A) characters.

     DOS files use CR-LF as a newline. Unix uses only the CR. 

     In Windows, CR is 13 (dec) is 0D (hex)
     In Windows, LF is 10 (dec) is 0A (hex)

     In Windows, print \n puts 0D0A in a file
     In Windows, print \r put 0D in a file
     In Windows, print \n\r puts 0D0A0D in a file

     In Windows, s/\n/a/ replaces 0D0A with 'a'
     In Windows, s/\r/a/ replaces 0A with 'a' (ignores 0D0A pairs)
     In Windows, s/\n\r/a/ replaces 0D0A0D with 'a'

     In Windows, s/a/\n/ replaces 'a' with 0D0A
     In Windows, s/a/\r/ replaces 'a' with 0D
     In Windows, s/a/\n\r/ replaces 'a' with 0D0A0D

Switch Summary
In addition to the -e switch Perl provides several other switches that are useful in creating one liners. You can see the full list of Perl switches by typing in "Perl -h".

Switches may be used separately. Switches may also be combined unless a switch requires arguments. If a switch requiring an argument is combined with other switches, Perl will confuse the adjoining switch letters as the argument of the preceding switch.

Some valid and invalid switch combinations are shown in the next examples.

     perl -p -e "print 'Hello' "    # valid - switches listed separately
     perl -pe   "print 'Hello' "    # valid - switches combined
     perl -ipe  "print 'Hello' "    # invalid - because -i requires argument

Not all of Perl's command line switches are equally useful in creating one liners. Here is a summary of the most frequently used switches. A more detailed description of using each switch is provided in the next section.

    -aautosplits input into @F array (whitespace default can be changed)
    -e programindicates that Perl statements will be supplied on the command line
    -F/pattern/changes the pattern input is split on with -a
    -i/extension    operates on files in-place, with optional backup via -i.bak
    -lhandles newlines
    -MM loads Perl module (examples: File::Slurp or IO::All)
    -nloops through input, without printing anything
    -0[octal](a zero) specifies the input record separator.
    -ploops through input @ARG, printing each line of input

Additional Switch Explanations
Here are additional details on using some of the more useful switches. The -n, -p and -i are most commonly used, and are discussed first. The -a, -F, -M, -O and -l are less commonly used and are described next.

    -p Switch - Looping Through a File
    The -p switch executes the one liner code in a loop, once for each line of text from the input files, printing each input line.

        perl -pe "s/\s+//g;" input.txt 
    
        Removes spaces from each line of input.txt, prints results
    

    The -p switch works by having Perl put the code "s/\s+//g" into the following loop:

          while (<>) {
              ... the code is put here
          } continue {
              print or die "-p destination: $!\n";
          }
    
    This loop reads each line of all input files, putting the content in $_. The one liner code is then executed for each line (each value of $_). Then the resulting value of $_ is printed.

    Since most Perl functions operate on $_ by default, this approach can simplify much of the code used in the one liner.

    -n Switch - Looping Through a File
    The -n switch does the same thing as the -p switch, except that it does not print each line.

        perl -ne "s/\s+//g;" input.txt 
    
        Removes spaces from each line of input.txt, does not print results
    

    The -n is used when printing each line is not desired, or where a custom print function is needed.

    -i Switch - Inplace Editing of Input File
    A file can be edited in place using the -i switch. In Windows the -i switch must be used with an extension, such as i.bak. The original file will be backed up using the supplied extension.

         perl -i.old -pe "s/\s+//g" input.txt    
    
         Removes all spaces using s/\s+//g
         i.old specifies backup extension of .old (input.txt.old)
         -p loops through the lines of input.txt
         -p also prints $_ after changes are made
        
    
    Use this with caution!. If you execute the command twice, you've may have overwritten your backups with the changed versions from the first run.

    -a and -F Switches: Autosplitting of Input Records
    The '-a' directs Perl to split each line from STDIN and to put the result into the array @F. This is particularly useful when files are formatted as columns of data (each column will be in a position of the array).

         perl -nae "print $F[2], \n" input.txt 
    
         prints out only the 3rd column of data in each line
         -n loops through the lines of input.txt
         input.txt lines are placed in $_
         -a split $_ into @F.  $F[2] is the 3rd element of the array
    
    The -F switch can be use to define an alternate delimiter for splitting input lines. The -F format can define a literal string, such as -F":" or the format can be a pattern such as -F/pattern/.

    -l Switch - Line processing
    The -l switch chomps each input record from STDIN and sets the output record delimiter. The output record delimiter is kept in the special variable $\ and has the default value of an empty string.

    Used with no argument, the -l switch sets the output record separator ($\) to the value of the input record separator, which is kept in the special variable $/ and whose default value is a newline.

    With no argument, the -l switch simply means that a newline is added to each print statement, simplifying the one liner code needed to print lines of data.

         perl -le "print 1; print 2"     # '1' on first line, '2' on next line
    
         perl -lpe "s/\s+//g" input.txt
    
         replaces all spaces with an empty string using s/\s+//g 
         -p loops through the lines of input.txt
         -p prints value of $_, after it is modified by the one liner code
         -l (no argument) forces -p to add $_ to the print statement
    

    -M Switch - Using Modules
    The -M switch loads a module and makes it available for the one liner code.

    
    

    -O Switch:
    The -0 switch uses an argument to set the value of the input record separator, which is kept in the special variable $/.

    It is very useful if you want to read a full paragraph or a full file into a single string. It also lets you define the end of records with a character other than a newline (this might apply in the case of custom database formats).

    The special value of -00 (same as $/="") reads paragraphs and the special value of -0777 (same as $/=undef) reads the entire file into a single string (called file slurp mode).

Converting One Liners to Full Scripts
To convert one liners into full Perl scripts requires more than simply copying the one liners into a text file. Here are some tips on making the conversion.

    Newline handling
    To use the -l switch, simply use it on the shebang line of your Perl script.

          #!/usr/bin/perl -l
    

    Looping over input (-p or -n)
    The looping code must be manually entered into the full script, as in the following example. Use the print statement for -p, but not for -n.

          while (<>) {
              ... the code is put here
          } continue {
              print
          }
    

    In Place Editing
    To convert the -i in-place option, simply loop through each file name found in the array @ARGV, opening/writing/close files as needed to match the results of your one liner code.

    The following code shows a straightforward approach to opening each file and reading it's lines, including backing up the original.

          @ARGV=('input1.txt','input2.txt');  # set file names
          foreach (@ARGV) {        # foreach to loop thru files
              open(IN,$_);         # open input file
              open(OUT,"> NEW.$_"; # open output file
              foreach () {     # loop thru all lines
                 print OUT;        # your code goes here
              }          
              close IN;            # close input file
              close OUT;           # close output file
              rename $_, "$_.BAK"  # rename original as backup
              rename "NEW.$_", $_  # rename new as original
          }
    

One Liner Links
These are some of the links I visited while preparing this tutorial on one liners.

If you have any suggestions or corrections, please let me know.