Michael Limberger
Need me? Email mike@limberger.ca
Regex
Perl One-Liners - Real World Examples
Patterns that have been in a fight
These are battle-tested one-liners for common tasks.
Logs
Show me.
perl -ne 'print "$1\n" if /(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/' app.log
perl -ne '$c++ if /error/i; END { print "$c\n" }' app.log
perl -ne 'print "$1\n" if /(\d+\.\d+\.\d+\.\d+)/' access.log | sort -u
Timestamps. Count lines containing "error". Unique IP addresses.
CSV
perl -F',' -ane 'print "$F[1]\n"' data.csv
perl -F',' -ane 'print "$F[1]\n" if $. > 1' data.csv
perl -F',' -ane 'print "$F[2],$F[0],$F[1]\n"' data.csv
Second column. Skip the header ($. is the line number). Reorder columns 3, 1, 2.
JSON, crudely
perl -ne 'print "$1\n" if /"name":\s*"([^"]+)"/' data.json
For serious JSON work, use jq. For a quick extract, this works.
Line endings and blank lines
perl -i -pe 's/\r\n/\n/' *.txt
perl -i -pe 's/\n/\r\n/' *.txt
perl -ne 'print unless /^$/' file.txt
perl -00 -pe '' file.txt
Windows to Unix. Unix to Windows. Remove blank lines. Collapse multiple blank lines to one. The -00 flag enables paragraph mode.
Base64, again
This comes up constantly with AI APIs.
cat image.b64 | perl -pe 's/\s//g'
perl -pe 's/(.{76})/$1\n/g' raw.b64
Strip whitespace. Add newlines every 76 characters, the standard wrap.
Vision responses
Given:
NUDE_CHEST: NO
NUDE_LOWER: NO
WEAPON: YES
CONFIDENCE: 0.87
Show me.
perl -ne 'print "$1\n" if /WEAPON:\s*(\w+)/' response.txt
perl -ne 'print "$1\n" if /(\w+):\s*YES/' response.txt
perl -ne 'print "$1\n" if /CONFIDENCE:\s*(\d+\.\d+)/' response.txt
Fix a typo across files
perl -i -pe 's/teh/the/g' *.txt
perl -i -pe 's/version: 1\.0/version: 1.1/' config.yml
perl -i -pe 's/^(.*DEBUG.*)$/# $1/' code.py
Reformat
perl -pe 's/\s+/,/g' data.txt
perl -pe 's/\t/ /g' file.txt
perl -pe 's/ +/ /g' file.txt
Spaces to commas. Tabs to four spaces. Collapse duplicate spaces.
URLs and email
perl -ne 'print "$1\n" while /(https?:\/\/[^\s"<>]+)/g' page.html
perl -ne 'print "$1\n" while /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g' file.txt
The while loop finds all matches, not just the first.
Pipes from other commands
curl -s https://example.com | perl -ne 'print "$1\n" if /<title>([^<]+)</'
find . -name "*.log" | perl -ne 'chomp; print "Found: $_\n"'
ack -o "\d+" | perl -ne '$sum += $_; END { print "Total: $sum\n" }'
The whole file as one string
perl -0777 -pe 's/old/new/g' file.txt
perl -0777 -pe 's|/\*.*?\*/||gs' code.c
-0777 slurps the whole file. Useful for patterns spanning lines. The second one strips C-style comments.
BEGIN and END
perl -ne 'BEGIN { $sum = 0 } $sum += $_; END { print $sum }' nums.txt
perl -pe 'BEGIN { print "=== OUTPUT ===\n" }' file.txt
The -l flag
perl -lne 'print uc' file.txt
Automatically chomps input and adds newlines to output. Cleaner than handling newlines by hand.
See what it is doing
perl -ne 'print "LINE: $_"; print "MATCH: $1\n" if /(\d+)/' file.txt
perl -MData::Dumper -ne '@F = split /,/; print Dumper(\@F)' data.csv
When the one-liner gets too long
Make it a script:
Show me.
#!/usr/bin/env perl
use strict;
use warnings;
while (<>) {
s/old/new/g;
print;
}
Save as script.pl, chmod +x, and run on any file. <> is the diamond operator: read from files named on the command line, or from stdin.
Speed, if the file is huge
Avoid capturing groups if you do not need them. Use index() for literal string matching. Pre-compile regex with qr// for repeated matches.
perl -ne 'BEGIN { $re = qr/pattern/ } print if /$re/' huge.txt