Portrait of Michael Limberger

Michael Limberger

Need me? Email mike@limberger.ca

Regex

Perl One-Liners - The Basics

A whole program on one line

Perl was designed for text processing. One-liners let you transform text without writing a script file. Quick find-and-replace. Extracting data. Reformatting on the fly. Piping between commands.

Same regex syntax as ack and rename. Learn once, use everywhere.

The shape

Show me.

perl [options] 'code' [files]
Flag Job
-e Execute code from the command line
-n Loop over input lines. Do not print by default
-p Loop over input lines. Print by default
-i Edit files in place
-l Automatic newline handling

The -e flag is almost always used. It says "here comes the code."

Hello universe

echo "hello world" | perl -pe 's/world/universe/'
# Output: hello universe

-p loops over input and prints each line. s/// does the substitution.

Files, or a pipe

perl -pe 's/old/new/g' file.txt
cat file.txt | perl -pe 's/old/new/g'

Both do the same thing.

-n versus -p

-p reads lines, runs code, prints the result. Most common. -n reads lines, runs code, does not print automatically. With -n you control what gets printed:

perl -ne 'print if /pattern/' file.txt

This prints only lines matching the pattern. Like grep.

In-place editing

perl -i -pe 's/old/new/g' file.txt

This changes the file. No undo. Safer: create a backup:

perl -i.bak -pe 's/old/new/g' file.txt

That saves the original as file.txt.bak before modifying.

Substitution, named out loud

perl -pe 's/foo/bar/g' input.txt > output.txt

Symbol map: -p print each line after processing. -e code follows. s/foo/bar/ replace foo with bar. /g global, all occurrences.

Case-insensitive and global: perl -pe 's/error/warning/gi' log.txt. The /i makes it case-insensitive.

Print matching lines

perl -ne 'print if /pattern/' file.txt
perl -ne 'print unless /pattern/' file.txt

The second is the inverse: non-matching lines.

Extract just the match

perl -ne 'print "$1\n" if /(\d+)/' file.txt

This prints captured numbers, one per line. Without a capture group, use $& for the whole match:

perl -ne 'print "$&\n" if /\d+/' file.txt

$& is Perl's whole-match variable. Ampersand, not a broken italic tag.

Several files

perl -pe 's/old/new/g' file1.txt file2.txt file3.txt
perl -i -pe 's/old/new/g' *.txt

The default variable $_

In Perl one-liners, $_ is the current line. Most operations work on $_ by default.

perl -ne 'print if /pattern/'

Is shorthand for:

perl -ne 'print $_ if $_ =~ /pattern/'

You rarely need to write $_ explicitly. When you do, it is dollar-underscore, not an italic.

Modify the line

perl -pe '$_ = uc'        # Uppercase
perl -pe '$_ = lc'        # Lowercase
perl -pe '$_ = reverse'   # Reverse each line
perl -pe 's/^\s+//'       # Leading whitespace
perl -pe 's/\s+$//'       # Trailing whitespace
perl -pe 's/^\s+|\s+$//g' # Trim both ends

Line numbers

perl -pe '$_ = "$. $_"' file.txt

$. is the current line number. Output looks like: 1 First line, 2 Second line, 3 Third line.

Fields

Split lines on whitespace and print specific fields:

perl -ane 'print "$F[0]\n"' file.txt
perl -ane 'print "$F[0] $F[2]\n"' file.txt
perl -F',' -ane 'print "$F[0]\n"' data.csv

The -a flag auto-splits into the @F array. Fields are zero-indexed. -F',' sets the field separator to a comma.

Sum the numbers

perl -ne '$sum += $_; END { print "$sum\n" }' numbers.txt

The END block runs after all lines are processed.