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.