Table of Contents

Some one liners: socher.org

Install local version of Perl without needing root access

If installing locally with a lighttpd webserver, see here for a lighttpd.conf file html css javascript

wget https://www.cpan.org/src/5.0/perl-5.34.0.tar.gz
tar -xzf perl-5.34.0.tar.gz
cd perl-5.34.0
mkdir -p $HOME/opt/perl
./Configure -des -Dprefix=$HOME/opt/perl
make
make test
make install
export PATH="${HOME}/opt/perl/bin:${PATH}"

Install additional modules locally without root access

Install this first one (Local::Lib) manually, the rest can be done using it.

mkdir ~/opt/perl/src
mv local-lib-2.000028.tar.gz ~/opt/perl/src/
cd ~/opt/perl/src/
tar -zxvf local-lib-2.000028.tar.gz
cd local-lib-2.000028
perl Makefile.PL PREFIX=~/opt/perl
make && make test && make install
perl -MCPAN -Mlocal::lib -e 'CPAN::install(Switch)'

Oneliners

Remove all non-ascii characters from a text file
If 'cat -v' shows up weird characters in the file, they can be removed like this:

perl -pe 's/[^[:ascii:]]/ /g;' bad_file > good_file

Print out just the connect identifiers of the connection clauses in tnsnames.ora
match an alphabetic or numeric (not space) as first character followed by any number of characters until the first =

perl -n -e 'print "$1\n" if m/^(\w.+?)=/' $TNS_ADMIN/tnsnames.ora|sort -u

To spit out only the stanzas in tnsnames.ora where the host and port are specific values

perl -ne 'BEGIN { $/="";} { chomp; push @stanzas, $_ if m/hn481/i && m/3529/; } END { push @stanzas, ""; print join "\n\n", @stanzas; }' tnsnames.ora

Change the connect identifier in tnsnames.ora to upper case (anything from the start of line up to “= (” )

perl -p -i -e 's/^(.+?)= \(/\U$1= \(/' $TNS_ADMIN/tnsnames.ora

To spit out only the stanzas in /etc/filesystems where mount is set to false

perl -ne 'BEGIN { $/="";} { s/\s+\=/ =/g;s/\n\s+/\n/g;s/^(\/.+):/mp = \1/;print "$_\n" if !m/^\*/ && m/mount\s+=\s+false/i; }' /etc/filesystems

To modify the value in a variable

$variable =~ s/regex/replacement/g;
eg:
$sid =~ s/ora_pmon_//;

To change only the fifth line, you can add a test checking $., the input line number, then only perform the operation when the test passes:

perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt

To add lines before a certain line, you can add a line (or lines!) before Perl prints $_:

perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt

You can even add a line to the beginning of a file, since the current line prints at the end of the loop:

perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt

To insert a line after one already in the file, use the -n switch. It's just like -p except that it doesn't print $_ at the end of the loop, so you have to do that yourself. In this case, print $_ first, then print the line that you want to add.

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt

To delete lines, only print the ones that you want.

perl -ni -e 'print unless /d/' inFile.txt

… or …

perl -pi -e 'next unless /d/' inFile.txt

Another set of useful one-liner tricks

Smart newline processing. Normally, perl hands you entire lines, including a trailing newline. With -l, it will strip the trailing newline off of any lines read, and automatically add a newline to anything you print (including via -p).

Suppose I wanted to strip trailing whitespace from a file. I might naïvely try something like

perl -pe 's/\s*$//'

The problem, however, is that the line ends with “\n”, which is whitespace, and so that snippet will also remove all newlines from my file! -l solves the problem, by pulling off the newline before handing my script the line, and then tacking a new one on afterwards:

perl -lpe 's/\s*$//'

Occasionally, it's useful to run a script over an entire file, or over larger chunks at once. -0 makes -n and -p feed you chunks split on NULL bytes instead of newlines. This is often useful for, e.g. processing the output of find -print0. Furthermore, perl -0777 makes perl not do any splitting, and pass entire files to your script in $_.

find . -name '*~' -print0 | perl -0ne unlink

Could be used to delete all ~-files in a directory tree, without having to remember how xargs works.

-i tells perl to operate on files in-place. If you use -n or -p with -i, and you pass perl filenames on the command-line, perl will run your script on those files, and then replace their contents with the output. -i optionally accepts an backup suffix as argument; Perl will write backup copies of edited files to names with that suffix added.

perl -i.bak -ne 'print unless /^#/' script.sh

Would strip all whole-line commands from script.sh, but leave a copy of the original in script.sh.bak.

Perl's .. operator is a stateful operator – it remembers state between evaluations. As long as its left operand is false, it returns false; Once the left hand returns true, it starts evaluating the right-hand operand until that becomes true, at which point, on the next iteration it resets to false and starts testing the other operand again.

What does that mean in practice? It's a range operator: It can be easily used to act on a range of lines in a file. For instance, I can extract all GPG public keys from a file using:

perl -ne 'print if /-----BEGIN PGP PUBLIC KEY BLOCK-----/../-----END PGP PUBLIC KEY BLOCK-----/' FILE

-a turns on autosplit mode – perl will automatically split input lines on whitespace into the @F array. If you ever run into any advice that accidentally escaped from 1980 telling you to use awk because it automatically splits lines into fields, this is how you use perl to do the same thing without learning another, even worse, language.

As an example, you could print a list of files along with their link counts using

ls -l | perl -lane 'print "$F[7] $F[1]"'

-F is used in conjunction with -a, to choose the delimiter on which to split lines. To print every user in /etc/passwd (which is colon-separated with the user in the first column), we could do:

perl -F: -lane 'print $F[0]' /etc/passwd

\K is undoubtedly my favorite little-known-feature of Perl regular expressions. If \K appears in a regex, it causes the regex matcher to drop everything before that point from the internal record of “Which string did this regex match?”.
This is most useful in conjunction with 's///', where it gives you a simple way to match a long expression, but only replace a suffix of it.

Suppose I want to replace the From: field in an email. We could write something like

perl -lape 's/(^From:).*/$1 Nelson Elhage <nelhage\@ksplice.com>/'

But having to parenthesize the right bit and include the $1 is annoying and error-prone. We can simplify the regex by using \K to tell perl we won't want to replace the start of the match:

perl -lape 's/^From:\K.*/ Nelson Elhage <nelhage\@ksplice.com>/'

When you're writing a one-liner using -e in the shell, you generally want to quote it with ', so that dollar signs inside the one-liner aren't expanded by the shell. But that makes it annoying to use a ' inside your one-liner, since you can't escape a single quote inside of single quotes, in the shell.

Let's suppose we wanted to print the username of anyone in /etc/passwd whose name included an apostrophe. One option would be to use a standard shell-quoting trick to include the ':

perl -F: -lane 'print $F[0] if $F[4] =~ /'"'"'/' /etc/passwd

But counting apostrophes and backslashes gets old fast. A better option, in my opinion, is to use the environment to pass the regex into perl, which lets you dodge a layer of parsing entirely:

env re="'" perl -F: -lane 'print $F[0] if $F[4] =~ /$ENV{re}/' /etc/passwd

We use the env command to place the regex in a variable called re, which we can then refer to from the perl script through the %ENV hash. This way is slightly longer, but I find the savings in counting backslashes or quotes to be worth it, especially if you need to end up embedding strings with more than a single metacharacter.

BEGIN { … } and END { … } let you put code that gets run entirely before or after the loop over the lines.

For example, I could sum the values in the second column of a CSV file using:

perl -F, -lane '$t += $F[1]; END { print $t }'

Using -M on the command line tells perl to load the given module before running your code. There are thousands of modules available on CPAN, numerous of them potentially useful in one-liners, but one of my favorite for one-liner use is Regexp::Common, which, as its name suggests, contains regular expressions to match numerous commonly-used pieces of data.

The full set of regexes available in Regexp::Common is available in its documentation, but here's an example of where I might use it:

Neither the ifconfig nor the ip tool that is supposed to replace it provide, as far as I know, an easy way of extracting information for use by scripts. The ifdata program provides such an interface, but isn't installed everywhere. Using perl and Regexp::Common, however, we can do a pretty decent job of extracing an IP from ips output:

ip address list eth0 | \nperl -MRegexp::Common -lne 'print $1 if /($RE{net}{IPv4})/'

Perl oneliners from catonmat.net

Reference: https://catonmat.net/ftp/perl1line.txt

Useful One-Line Scripts for Perl                    Jan 27 2019 | version 1.12
--------------------------------                    -----------   ------------

Compiled by Peter Krumins ([email protected], @pkrumins on twitter)
https://www.catonmat.net -- good coders code, great coders reuse

Latest version of this file is always at:

    https://catonmat.net/ftp/perl1line.txt

This file is also available in other languages:

    Chinese: https://github.com/vinian/perl1line.txt

    Please email me [email protected] if you want to translate it.

Perl One-Liners on Github:
 
    https://github.com/pkrumins/perl1line.txt

    You can send me pull requests over GitHub! I accept bug fixes,
    new one-liners, translations and everything else related.

I have also written "Perl One-Liners Explained" ebook that's based on
this file. It explains all the one-liners here. Get it at:

    https://catonmat.net/perl-book

No Starch Press has published "Perl One-Liners" as a real book too:

    https://nostarch.com/perloneliners

These one-liners work both on UNIX systems and Windows. Most likely your
UNIX system already has Perl. For Windows get the Strawberry Perl at:

    http://www.strawberryperl.com

Table of contents:

    1. File Spacing
    2. Line Numbering
    3. Calculations
    4. String Creation and Array Creation
    5. Text Conversion and Substitution
    6. Selective Printing and Deleting of Certain Lines    
    7. Handy Regular Expressions
    8. Perl tricks


FILE SPACING 
------------

# Double space a file
perl -pe '$\="\n"'
perl -pe 'BEGIN { $\="\n" }'
perl -pe '$_ .= "\n"'
perl -pe 's/$/\n/'
perl -nE 'say'

# Double space a file, except the blank lines
perl -pe '$_ .= "\n" unless /^$/'
perl -pe '$_ .= "\n" if /\S/'

# Triple space a file
perl -pe '$\="\n\n"'
perl -pe '$_.="\n\n"'

# N-space a file
perl -pe '$_.="\n"x7'

# Add a blank line before every line
perl -pe 's//\n/'

# Remove all blank lines
perl -ne 'print unless /^$/'
perl -lne 'print if length'
perl -ne 'print if /\S/'

# Remove all consecutive blank lines, leaving just one
perl -00 -pe ''
perl -00pe0

# Compress/expand all blank lines into N consecutive ones
perl -00 -pe '$_.="\n"x4'

# Fold a file so that every set of 10 lines becomes one tab-separated line
perl -lpe '$\ = $. % 10 ? "\t" : "\n"'


LINE NUMBERING
--------------

# Number all lines in a file
perl -pe '$_ = "$. $_"'

# Number only non-empty lines in a file
perl -pe '$_ = ++$a." $_" if /./'

# Number and print only non-empty lines in a file (drop empty lines)
perl -ne 'print ++$a." $_" if /./'

# Number all lines but print line numbers only non-empty lines
perl -pe '$_ = "$. $_" if /./'

# Number only lines that match a pattern, print others unmodified
perl -pe '$_ = ++$a." $_" if /regex/'

# Number and print only lines that match a pattern
perl -ne 'print ++$a." $_" if /regex/'

# Number all lines, but print line numbers only for lines that match a pattern
perl -pe '$_ = "$. $_" if /regex/'

# Number all lines in a file using a custom format (emulate cat -n)
perl -ne 'printf "%-5d %s", $., $_'

# Print the total number of lines in a file (emulate wc -l)
perl -lne 'END { print $. }'
perl -le 'print $n=()=<>'
perl -le 'print scalar(()=<>)'
perl -le 'print scalar(@foo=<>)'
perl -ne '}{print $.'
perl -nE '}{say $.'

# Print the number of non-empty lines in a file
perl -le 'print scalar(grep{/./}<>)'
perl -le 'print ~~grep{/./}<>'
perl -le 'print~~grep/./,<>'
perl -E 'say~~grep/./,<>'

# Print the number of empty lines in a file
perl -lne '$a++ if /^$/; END {print $a+0}'
perl -le 'print scalar(grep{/^$/}<>)'
perl -le 'print ~~grep{/^$/}<>'
perl -E 'say~~grep{/^$/}<>'

# Print the number of lines in a file that match a pattern (emulate grep -c)
perl -lne '$a++ if /regex/; END {print $a+0}'
perl -nE '$a++ if /regex/; END {say $a+0}'


CALCULATIONS
------------

# Check if a number is a prime
perl -lne '(1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ is prime"'

# Print the sum of all the fields on a line
perl -MList::Util=sum -alne 'print sum @F'

# Print the sum of all the fields on all lines
perl -MList::Util=sum -alne 'push @S,@F; END { print sum @S }'
perl -MList::Util=sum -alne '$s += sum @F; END { print $s }'

# Shuffle all fields on a line
perl -MList::Util=shuffle -alne 'print "@{[shuffle @F]}"'
perl -MList::Util=shuffle -alne 'print join " ", shuffle @F'

# Find the minimum element on a line
perl -MList::Util=min -alne 'print min @F'

# Find the minimum element over all the lines
perl -MList::Util=min -alne '@M = (@M, @F); END { print min @M }'
perl -MList::Util=min -alne '$min = min @F; $rmin = $min unless defined $rmin && $min > $rmin; END { print $rmin }'

# Find the maximum element on a line
perl -MList::Util=max -alne 'print max @F'

# Find the maximum element over all the lines
perl -MList::Util=max -alne '@M = (@M, @F); END { print max @M }'

# Replace each field with its absolute value
perl -alne 'print "@{[map { abs } @F]}"'

# Find the total number of fields (words) on each line
perl -alne 'print scalar @F'

# Print the total number of fields (words) on each line followed by the line
perl -alne 'print scalar @F, " $_"'

# Find the total number of fields (words) on all lines
perl -alne '$t += @F; END { print $t}'

# Print the total number of fields that match a pattern
perl -alne 'map { /regex/ && $t++ } @F; END { print $t }'
perl -alne '$t += /regex/ for @F; END { print $t }'
perl -alne '$t += grep /regex/, @F; END { print $t }'

# Print the total number of lines that match a pattern
perl -lne '/regex/ && $t++; END { print $t }'

# Print the number PI to n decimal places
perl -Mbignum=bpi -le 'print bpi(n)'

# Print the number PI to 39 decimal places
perl -Mbignum=PI -le 'print PI'

# Print the number E to n decimal places
perl -Mbignum=bexp -le 'print bexp(1,n+1)'

# Print the number E to 39 decimal places
perl -Mbignum=e -le 'print e'

# Print UNIX time (seconds since Jan 1, 1970, 00:00:00 UTC)
perl -le 'print time'

# Print GMT (Greenwich Mean Time) and local computer time
perl -le 'print scalar gmtime'
perl -le 'print scalar localtime'

# Print local computer time in H:M:S format
perl -le 'print join ":", (localtime)[2,1,0]'

# Print yesterday's date
perl -MPOSIX -le '@now = localtime; $now[3] -= 1; print scalar localtime mktime @now'

# Print date 14 months, 9 days and 7 seconds ago
perl -MPOSIX -le '@now = localtime; $now[0] -= 7; $now[4] -= 14; $now[7] -= 9; print scalar localtime mktime @now'

# Prepend timestamps to stdout (GMT, localtime)
tail -f logfile | perl -ne 'print scalar gmtime," ",$_'
tail -f logfile | perl -ne 'print scalar localtime," ",$_'

# Calculate factorial of 5
perl -MMath::BigInt -le 'print Math::BigInt->new(5)->bfac()'
perl -le '$f = 1; $f *= $_ for 1..5; print $f'

# Calculate greatest common divisor (GCM)
perl -MMath::BigInt=bgcd -le 'print bgcd(@list_of_numbers)'

# Calculate GCM of numbers 20 and 35 using Euclid's algorithm
perl -le '$n = 20; $m = 35; ($m,$n) = ($n,$m%$n) while $n; print $m'

# Calculate least common multiple (LCM) of numbers 35, 20 and 8
perl -MMath::BigInt=blcm -le 'print blcm(35,20,8)'

# Calculate LCM of 20 and 35 using Euclid's formula: n*m/gcd(n,m)
perl -le '$a = $n = 20; $b = $m = 35; ($m,$n) = ($n,$m%$n) while $n; print $a*$b/$m'

# Generate 10 random numbers between 5 and 15 (excluding 15)
perl -le '$n=10; $min=5; $max=15; $, = " "; print map { int(rand($max-$min))+$min } 1..$n'

# Find and print all permutations of a list
perl -MAlgorithm::Permute -le '$l = [1,2,3,4,5]; $p = Algorithm::Permute->new($l); print @r while @r = $p->next'

# Generate the power set
perl -MList::PowerSet=powerset -le '@l = (1,2,3,4,5); for (@{powerset(@l)}) { print "@$_" }'

# Convert an IP address to unsigned integer
perl -le '$i=3; $u += ($_<<8*$i--) for "127.0.0.1" =~ /(\d+)/g; print $u'
perl -le '$ip="127.0.0.1"; $ip =~ s/(\d+)\.?/sprintf("%02x", $1)/ge; print hex($ip)'
perl -le 'print unpack("N", 127.0.0.1)'
perl -MSocket -le 'print unpack("N", inet_aton("127.0.0.1"))'

# Convert an unsigned integer to an IP address
perl -MSocket -le 'print inet_ntoa(pack("N", 2130706433))'
perl -le '$ip = 2130706433; print join ".", map { (($ip>>8*($_))&0xFF) } reverse 0..3'
perl -le '$ip = 2130706433; $, = "."; print map { (($ip>>8*($_))&0xFF) } reverse 0..3'


STRING CREATION AND ARRAY CREATION
----------------------------------

# Generate and print the alphabet
perl -le 'print a..z'
perl -le 'print ("a".."z")'
perl -le '$, = ","; print ("a".."z")'
perl -le 'print join ",", ("a".."z")'

# Generate and print all the strings from "a" to "zz"
perl -le 'print ("a".."zz")'
perl -le 'print "aa".."zz"'

# Create a hex lookup table
@hex = (0..9, "a".."f")

# Convert a decimal number to hex using @hex lookup table
perl -le '$num = 255; @hex = (0..9, "a".."f"); while ($num) { $s = $hex[($num%16)&15].$s; $num = int $num/16 } print $s'
perl -le '$hex = sprintf("%x", 255); print $hex'
perl -le '$num = "ff"; print hex $num'

# Generate a random 8 character password
perl -le 'print map { ("a".."z")[rand 26] } 1..8'
perl -le 'print map { ("a".."z", 0..9)[rand 36] } 1..8'

# Create a string of specific length
perl -le 'print "a"x50'

# Create a repeated list of elements
perl -le '@list = (1,2)x20; print "@list"'

# Create an array from a string
@months = split ' ', "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
@months = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/

# Create a string from an array
@stuff = ("hello", 0..9, "world"); $string = join '-', @stuff

# Find the numeric values for characters in the string
perl -le 'print join ", ", map { ord } split //, "hello world"'

# Convert a list of numeric ASCII values into a string
perl -le '@ascii = (99, 111, 100, 105, 110, 103); print pack("C*", @ascii)'
perl -le '@ascii = (99, 111, 100, 105, 110, 103); print map { chr } @ascii'

# Generate an array with odd numbers from 1 to 100
perl -le '@odd = grep {$_ % 2 == 1} 1..100; print "@odd"'
perl -le '@odd = grep { $_ & 1 } 1..100; print "@odd"'

# Generate an array with even numbers from 1 to 100
perl -le '@even = grep {$_ % 2 == 0} 1..100; print "@even"'

# Find the length of the string
perl -le 'print length "one-liners are great"'

# Find the number of elements in an array
perl -le '@array = ("a".."z"); print scalar @array'
perl -le '@array = ("a".."z"); print $#array + 1'


TEXT CONVERSION AND SUBSTITUTION
--------------------------------

# ROT13 a string
'y/A-Za-z/N-ZA-Mn-za-m/'

# ROT 13 a file
perl -lpe 'y/A-Za-z/N-ZA-Mn-za-m/' file

# Base64 encode a string
perl -MMIME::Base64 -e 'print encode_base64("string")'
perl -MMIME::Base64 -0777 -ne 'print encode_base64($_)' file

# Base64 decode a string
perl -MMIME::Base64 -le 'print decode_base64("base64string")'
perl -MMIME::Base64 -ne 'print decode_base64($_)' file

# URL-escape a string
perl -MURI::Escape -le 'print uri_escape($string)'

# URL-unescape a string
perl -MURI::Escape -le 'print uri_unescape($string)'

# HTML-encode a string
perl -MHTML::Entities -le 'print encode_entities($string)'

# HTML-decode a string
perl -MHTML::Entities -le 'print decode_entities($string)'

# Convert all text to uppercase
perl -nle 'print uc'
perl -ple '$_=uc'
perl -nle 'print "\U$_"'

# Convert all text to lowercase
perl -nle 'print lc'
perl -ple '$_=lc'
perl -nle 'print "\L$_"'

# Uppercase only the first word of each line
perl -nle 'print ucfirst lc'
perl -nle 'print "\u\L$_"'

# Invert the letter case
perl -ple 'y/A-Za-z/a-zA-Z/'

# Camel case each line
perl -ple 's/(\w+)/\u$1/g'
perl -ple 's/(?<![\'])(\w+)/\u\1/g'

# Strip leading whitespace (spaces, tabs) from the beginning of each line
perl -ple 's/^[ \t]+//'
perl -ple 's/^\s+//'

# Strip trailing whitespace (space, tabs) from the end of each line
perl -ple 's/[ \t]+$//'

# Strip whitespace from the beginning and end of each line
perl -ple 's/^[ \t]+|[ \t]+$//g'

# Convert UNIX newlines to DOS/Windows newlines
perl -pe 's|\n|\r\n|'

# Convert DOS/Windows newlines to UNIX newlines
perl -pe 's|\r\n|\n|'

# Convert UNIX newlines to Mac newlines
perl -pe 's|\n|\r|'

# Substitute (find and replace) "foo" with "bar" on each line
perl -pe 's/foo/bar/'

# Substitute (find and replace) all "foo"s with "bar" on each line
perl -pe 's/foo/bar/g'

# Substitute (find and replace) "foo" with "bar" on lines that match "baz"
perl -pe '/baz/ && s/foo/bar/'

# Binary patch a file (find and replace a given array of bytes as hex numbers)
perl -pi -e 's/\x89\xD8\x48\x8B/\x90\x90\x48\x8B/g' file


SELECTIVE PRINTING AND DELETING OF CERTAIN LINES
------------------------------------------------

# Print the first line of a file (emulate head -1)
perl -ne 'print; exit'

# Print the first 10 lines of a file (emulate head -10)
perl -ne 'print if $. <= 10'
perl -ne '$. <= 10 && print'
perl -ne 'print if 1..10'

# Print the last line of a file (emulate tail -1)
perl -ne '$last = $_; END { print $last }'
perl -ne 'print if eof'

# Print the last 10 lines of a file (emulate tail -10)
perl -ne 'push @a, $_; @a = @a[@a-10..$#a]; END { print @a }'

# Print only lines that match a regular expression
perl -ne '/regex/ && print'

# Print only lines that do not match a regular expression
perl -ne '!/regex/ && print'

# Print the line before a line that matches a regular expression
perl -ne '/regex/ && $last && print $last; $last = $_'

# Print the line after a line that matches a regular expression
perl -ne 'if ($p) { print; $p = 0 } $p++ if /regex/'

# Print lines that match regex AAA and regex BBB in any order
perl -ne '/AAA/ && /BBB/ && print'

# Print lines that don't match match regexes AAA and BBB
perl -ne '!/AAA/ && !/BBB/ && print'

# Print lines that match regex AAA followed by regex BBB followed by CCC
perl -ne '/AAA.*BBB.*CCC/ && print'

# Print lines that are 80 chars or longer
perl -ne 'print if length >= 80'

# Print lines that are less than 80 chars in length
perl -ne 'print if length < 80'

# Print only line 13
perl -ne '$. == 13 && print && exit'

# Print all lines except line 27
perl -ne '$. != 27 && print'
perl -ne 'print if $. != 27'

# Print only lines 13, 19 and 67
perl -ne 'print if $. == 13 || $. == 19 || $. == 67'
perl -ne 'print if int($.) ~~ (13, 19, 67)' 

# Print all lines between two regexes (including lines that match regex)
perl -ne 'print if /regex1/../regex2/'

# Print all lines from line 17 to line 30
perl -ne 'print if $. >= 17 && $. <= 30'
perl -ne 'print if int($.) ~~ (17..30)'
perl -ne 'print if grep { $_ == $. } 17..30'

# Print the longest line
perl -ne '$l = $_ if length($_) > length($l); END { print $l }'

# Print the shortest line
perl -ne '$s = $_ if $. == 1; $s = $_ if length($_) < length($s); END { print $s }'

# Print all lines that contain a number
perl -ne 'print if /\d/'

# Find all lines that contain only a number
perl -ne 'print if /^\d+$/'

# Print all lines that contain only characters
perl -ne 'print if /^[[:alpha:]]+$/'

# Print every second line
perl -ne 'print if $. % 2'

# Print every second line, starting the second line
perl -ne 'print if $. % 2 == 0'

# Print all lines that repeat
perl -ne 'print if ++$a{$_} == 2'

# Print all unique lines
perl -ne 'print unless $a{$_}++'

# Print the first field (word) of every line (emulate cut -f 1 -d ' ')
perl -alne 'print $F[0]'


HANDY REGULAR EXPRESSIONS
-------------------------

# Match something that looks like an IP address
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
/^(\d{1,3}\.){3}\d{1,3}$/

# Test if a number is in range 0-255
/^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/

# Match an IP address
my $ip_part = qr|([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|;
if ($ip =~ /^($ip_part\.){3}$ip_part$/) {
 say "valid ip";
}

# Check if the string looks like an email address
/\S+@\S+\.\S+/

# Check if the string is a decimal number
/^\d+$/
/^[+-]?\d+$/
/^[+-]?\d+\.?\d*$/

# Check if the string is a hexadecimal number
/^0x[0-9a-f]+$/i

# Check if the string is an octal number
/^0[0-7]+$/

# Check if the string is binary
/^[01]+$/

# Check if a word appears twice in the string
/(word).*\1/

# Increase all numbers by one in the string
$str =~ s/(\d+)/$1+1/ge

# Extract HTTP User-Agent string from the HTTP headers
/^User-Agent: (.+)$/

# Match printable ASCII characters
/[ -~]/

# Match unprintable ASCII characters
/[^ -~]/

# Match text between two HTML tags
m|<strong>([^<]*)</strong>|
m|<strong>(.*?)</strong>|

# Replace all <b> tags with <strong>
$html =~ s|<(/)?b>|<$1strong>|g

# Extract all matches from a regular expression
my @matches = $text =~ /regex/g;


PERL TRICKS
-----------

# Print the version of a Perl module
perl -MModule -le 'print $Module::VERSION'
perl -MLWP::UserAgent -le 'print $LWP::UserAgent::VERSION'


PERL ONE-LINERS EXPLAINED E-BOOK
--------------------------------

I have written an ebook based on the one-liners in this file. If you want to
support my work and learn more about these one-liners, you can get a copy
of my ebook at:

    https://catonmat.net/perl-book

The ebook is based on the 7-part article series that I wrote on my blog.
In the ebook I reviewed all the one-liners, improved explanations, added
new ones, and added two new chapters - introduction to Perl one-liners
and summary of commonly used special variables.

You can read the original article series here:

    https://catonmat.net/perl-one-liners-explained-part-one
    https://catonmat.net/perl-one-liners-explained-part-two
    https://catonmat.net/perl-one-liners-explained-part-three
    https://catonmat.net/perl-one-liners-explained-part-four
    https://catonmat.net/perl-one-liners-explained-part-five
    https://catonmat.net/perl-one-liners-explained-part-six
    https://catonmat.net/perl-one-liners-explained-part-seven


CREDITS
-------

Andy Lester       http://www.petdance.com
Shlomi Fish       http://www.shlomifish.org
Madars Virza      http://www.madars.org
caffecaldo        https://github.com/caffecaldo
Kirk Kimmel       https://github.com/kimmel
avar              https://github.com/avar
rent0n


FOUND A BUG? HAVE ANOTHER ONE-LINER?
------------------------------------

Email bugs and new one-liners to me at [email protected].


HAVE FUN
--------

I hope you found these one-liners useful. Have fun and see ya!

#---end of file---

Using %ENV to pass parameters to a perl one-liner

Used here to clean up a comma-separated list of parameters passed into a shell.

  -  - remove all spaces
  -  - remove any quote characters
  -  - replace , with ','
  -  -----------------------------
SCHEMAE=`export quot="'"; echo $SCHEMAE | perl -lpe 's/\\s+//g; s/$ENV{quot}//g; s/,/$ENV{quot},$ENV{quot}/g'`

Add a line after another one in a file using Perl

Use Perl to filter a script (or a load of scripts) and add an extra line when certain pattern match condition exists.
Uses -n switch with print because using -p switch evaluates your condition first and then prints the line. This could be used if you want to print a line before the matched line!

for commvaulthost in ci00031669-hn491 ci00031670-hn492 ci00031671-hn5407 ci00031672-hn364 ci00031673-hn5207 ci00031674-hn5217; do
    unixhost=$(echo ${commvaulthost} | awk -F\\- '{print $NF}')
    perl -n -i -e 'print;print "TO_CV_HOST='${commvaulthost}'                                              # Commvault host\n" if /TO_HOST='${unixhost}'/' synchro*.cfg
done

perl -a

Turns on autosplit mode. Use -F<delim> to specify how to split the elements
Breaks down the input into elements of an automatically assigned array called @F.

perl -F: -lane 'print $F[0]' /etc/passwd

perl -l

When trimming whitespace from your input, the \n is removed also. Using -l adds it back in at the end of processing.
See examples above.

BEGIN and END

Allows you to run code before or after the loop over the lines.
Example, sum the values in the second column of a CSV file…
Replace the 'n' with a 'p' to see the numbers being summed.

perl -F, -lane '$sum += $F[1]; END { print $sum }' somefile.csv

.. operater

Cut chunks out of a file from /start range marker/ .. /end range marker/

perl -ne 'print if /-----BEGIN PGP PUBLIC KEY BLOCK-----/../-----END PGP PUBLIC KEY BLOCK-----/' file_containing_public_keys.txt

A one-liner web server!

perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'

From: commandlinefu.com

This can be used as a test status page to see if the cgi-bin directory is working properly. And that Perl is processing the files correctly.

#!perl

print "Content-type: text/html\n\n";
print "<font size=+1>Environment</font>\n";

foreach (sort keys %ENV) {
   print "<b>$_</b>: $ENV{$_}<br>\n";
}

1;

or

#!perl

use HTML::Perlinfo;
use CGI qw(header);

$q = new CGI;
print $q->header;

print "<html><head><title>Perl Info</title></head>";
print "<body><p><a href='http://localhost/ampps'>Back to AMPPS Home</a></p><center><h2>Perl Info</h2></center>";
print "</body></html>";

$p = new HTML::Perlinfo;
$p->info_general;
$p->info_variables;
$p->info_modules;
$p->info_license;

Retrieve a file from an authenticated website using Perl

This site (https://jmorano.moretrix.com/2011/02/retrieve-a-file-from-an-authenticated-website-in-perl/) shows how to do it using LWP. Replicating it here in case the original goes down.

Call your modules

#!/usr/bin/perl
use strict; use warnings;

use LWP;
use HTTP::Cookies;
use HTTP::Request;
use File::Path qw{mkpath};

The modules HTTP::Cookies and HTTP::Request are required to create the cookie jar file and to make a HTTP request (duh!). These two modules will create the objects that are required for the LWP user-agent object we are about to create.

Check your temporary path:

my $HOME = $ENV{HOME} . '/tmp';
mkpath $HOME   unless -d $HOME;

We will need this location to save our cookie jar file and the file we want to download

Create a cookie jar and a LWP user-agent:

# create a cookie jar on disk
my $cookies = HTTP::Cookies->new(
        file     => $HOME.'/cookies.txt',
        autosave => 1,
        );

# create an user-agent and assign the cookie jar to it
my $http = LWP::UserAgent->new();
$http->cookie_jar($cookies);

No rocket science here, just create the objects!

Send the authentication request:

# try to log in
my $login = $http->post(
        'https://www.example.com/auth/login.pl', [
            username => 'user',
            password => 'secret', ]
        );

Once authenticated, the web site will create a cookie containing a session ID. This cookie will allow us to download the file we need from the secured part of the web site. From this point on, it is required to check whether the log in succeeded and then continue with downloading the file. If the log in failed, an error message should be displayed with the reason on the failure.

# check if log in succeeded
if($login->is_success){
    print "- logged in successfully\n";
    print "- requesting file, might take a while\n";

    # make request to download the file
    my $url       = 'https://www.example.com/auth/files/backup.zip';
    my $file_req  = HTTP::Request->new('GET', $url);
    my $get_file  = $http->request( $file_req );

    # check request status
    if($get_file->is_success){
        print "--> downloaded $url, saving it to file\n";

        # save the file content to disk
        open my $fh, '>', $HOME.'/backup.zip' 
                                         or die "ERROR: $!\n";
        print $fh $get_file->decoded_content;
        close $fh;

        print "\nsaved file:\n";
        print "-------------\n";
        print "filename:  ".$get_file->filename."\n";
        print "size:      ".(-s $HOME.'/backup.zip')."\n";
    }
    else {
        die "ERROR: download of $url failed: " . $get_file->status_line . "\n";
    }
}
else {
    die "ERROR: login failed: " . $login->status_line . "\n";
}

What Perl modules are installed?

As found by typing “perldoc q installed”

#!/usr/bin/perl
use File::Find;
my @files;
find(
    sub {
        push @files, $File::Find::name
        if -f $File::Find::name && /\.pm$/
        },
    @INC
    );
print join "\n", @files;

Prepend a line at the beginning of a file

Surprisingly tricky thing to do as a one-liner. Seemingly cannot be done (cross-platform) in ksh in one line.

perl -p -i -e 'print "This is line 1 now!\n" if $. == 1' file.txt

Implement a socket client/server in Perl

thegeekstuff.com

Scan for emails with attachments and save attachments to files

Install a Perl module from CPAN

perl -MCPAN -e 'install RRD::Simple'
perl -ae 'print "$F[0]:$F[-1]\n"'

Mass update of files using perl inline script

for server in $(cat /home/tools/etc/oracle/oracle_servers); do
    ssh $server "perl -p -i -e 's/T01/D01/' /home/tools/scripts/rman/inclexcl.lst"
done

Perl emulation of dos2unix command

perl -p -i -e 's/\r\n/\n/' filename

and then back again with unix2dos

perl -p -i -e 's/[!\r]\n/\r\n/' filename
perl -ne 'next if (/pattern_for_removal/); print;' filename

Difference between double dot and triple dot operator

They can both work as flip-flop operators. The double dot will check the second pattern if it is on the same line as the first. For the triple dot to work, the end pattern must be on a different line from the begin pattern.
Explained better here

Exclude the first few lines of a file

perl -ne 'print unless 1 .. 10' filename
perl -ne 'print if /START/ .. /STOP/' filename
perl -ne 'print if /pattern1/ ... /pattern2/ and !/pattern1/ and !/pattern2/' filename
perl -ne 'print unless /START/ .. /STOP/' filename

Delete the last line of a file

perl -e '@x=<>; pop(@x); print @x'
perl -ne 'print if 15 .. 17'

but more efficiently…

perl -ne 'print if $. >= 15; exit if $. >= 17;'
perl -e 'print reverse <>' filename
perl -nle 'print scalar reverse $_' filename

Find palindromes in a file

perl -lne '$_ = lc; print if $_ eq reverse' filename

Reverse all the characters in a file

perl -0777e 'print scalar reverse <>' filename

Reverse all the characters in a paragraph but keeping the paragraphs in order

perl -00 -e 'print reverse <>' filename

Trim all heading and trailing spaces and compress any intermediate spaces to 1

perl -pe '$_ = " $_ "; tr/ \t/ /s; $_ = substr($_,1,-1)'

Nice one to reformat a document so that all lines are between 50 and 70 characters long. Only breaks on whitespace

perl -000 -p -e 'tr/ \t\nr/ /;s/(.{50,72})\s/$1\n/g;$_.="\n"x2'

Assign modified text in a variable keeping th original as it was

I aways forget the syntax for this so hopefully I will find this next time I need it!

($result = $subject) =~ s/before/after/g;
perl -ne '$q=($_=~tr/"//); print"$.\t$q\t$_";' filename

Capitalise all words in a file (ensuring all others letters in the words are lower case)

ref: Matz Kindahl

perl -pe 's/\w.+/\u\L$&/'

Translate into Zafir language!

perl -pe 's#\w+#ucfirst lc reverse $&#eg' filename

Read in (include) a configuration file in Perl

Although there are several ways to “include” files into the current program, this method is the simplest.
The problem with using require or include is that the scope is different so any my variables won't be visible
The trick here is the use of the “our” hash.

# ====================
# bring in config file
# ====================
our %config;
open (CONFIG, "<./config.txt") or die "Cannot locate configuration file";
while (<CONFIG>) {
    chomp; s/#.*//; s/^\s+//; s/\s+$//;
    next unless /=/;
    my ($var, $value) = split(/\s*=\s*/, $_, 2);
    $config{$var} = $value;
}
close CONFIG;

Send an email from perl without needing any external modules

but it only works on Unix

  # Simple Email Function
  # ($to, $from, $subject, $message)
sub sendemail
{
    my ($to, $from, $subject, $message) = @_;
    my $sendmail = '/usr/lib/sendmail';
    open(MAIL, "|$sendmail -oi -t");
    print MAIL "From: $from\n";
    print MAIL "To: $to\n";
    print MAIL "Subject: $subject\n\n";
    print MAIL "$message\n";
    close(MAIL);
}

Using the function is straightforward. Simply pass it the data in the correct order.

sendemail ( "toemail\@mydomain.com", "fromemail\@mydomain.com", "Simple email.", "This is a test of the email function." );

What "day of the year" (DOY) number was it yesterday?

YESTERDAY=`perl -e 'print sub{$_[7]}->(localtime);'`

What "day of the year" (DOY) number is it today?

TODAY=`perl -e 'print sub{$_[7]}->(localtime)+1;';`

Sort a list

Numerically

@sorted = sort { $a <=> $b } @unsorted

Alphabetically

@sorted = sort { $a cmp $b } @unsorted

Alphabetically (case-insensitive)

@sorted = sort { lc($a) cmp lc($b) } @unsorted

Schwartzian transform

    my @quickly_sorted_files =
    map { $_->[0] }
    sort { $a->[1] <=> $b->[1] }
    map { [$_, -s $_] }
    @files;

broken down into (semi)understandable pieces looks like this…

    my @unsorted_pairs = map { [$_, -s $_] } @files;
    my @sorted_pairs = sort { $a->[1] <=> $b->[1] } @unsorted_pairs;
    my @quickly_sorted_files = map { $_->[0] } @sorted_pairs;

Use 'map' to apply transformations

Push the list in one side (right) and get it back on the other (left) with some transformation applied.
Inside the code block, you refer to the current element with the traditional $_ variable.

my @langs = qw(perl php python);
my @langs = map { uc($_) } @langs;
Result: PERL PHP PYTHON

Use it with join to create clever stuff…

sub make_query_string {
   my ( $vals ) = @_;
   return join("&", map { "$_=$vals->{$_}" } keys %$vals);
}
my %query_params = (
   a => 1,
   b => 2,
   c => 3,
   d => 4,
);
my $query_string = make_query_string(\%query_params);
Result: &a=1&b=2&c=3&d=4

Difference in hours between two dates

use Time::localtime;
use DateTime::Format::Strptime qw();

        my $parser = DateTime::Format::Strptime->new (
            pattern  => '%d-%b-%y %H:%M:%S',
            locale   => 'en',   # 'Mon', 'Jul' are English
            on_error => 'croak'
        );
        my $timethen = $parser->parse_datetime( $started );
        my $timenow  = DateTime->now( time_zone => 'local' )->set_time_zone('floating');
        my $timediff = $timenow->subtract_datetime($timethen);

print ('<!-- HOURS: ',$timediff->hours(),' -->',"\n");

or, without using any external modules…

        my ($host,$sid,$dbid,$timethen,$recid,$stamp,$started,$duration,$size,$status,$type) = split (/\|/);

        # ----------------------------
        # work out how old the file is
        # ----------------------------
        my $timenow    = time();
        my $difference = $timenow - $timethen;  # in seconds
        my $hours      = $difference/60/60;
        $difference    = $difference - ($hours*60*60);
        my $mins       = $difference/60;
        my $secs       = $difference - ($mins*60);

Slurp an external file into a variable

The idea is to read an SQL file into a variable to prepare and execute it

#!/usr/bin/perl -w
use strict;
my $stmt;
my $quoted_stmt;
$quoted_stmt = 7;
open (FH,"<","test.sql") or die $!;
local $/ = undef;
$stmt = <FH>;
close FH;
$quoted_stmt = eval('q('.$stmt.')');
print $quoted_stmt."\n";

Search for a (list of) keyword(s) in a file

Could write this in several loops but here is a very neat way. Spotted on Stackoverflow.com

#!usr/bin/perl
use strict;
use warnings;

# Lexical variable for filehandle is preferred, and always error check opens.
open my $keywords,    '<', 'keywords.txt' or die "Can't open keywords: $!";
open my $search_file, '<', 'search.txt'   or die "Can't open search file: $!";

my $keyword_or = join '|', map {chomp;qr/\Q$_\E/} <$keywords>;
my $regex = qr|\b($keyword_or)\b|;

while (<$search_file>)
{
    while (/$regex/g)
    {
        print "$.: $1\n";
    }
}

basically it builds up a regular expression and searches for it.
See reference link for more details.\<br /> Can also be done very neatly with grep in shell

grep -n -f keywords.txt filewithlotsalines.txt

where keywords.txt is a file containing the list of words to search for.

Assign and substitute a value to a variable in one statement

Keep forgetting where the parentheses go so have to write it down…
Have to pre-define the variable $new_var otherwise you will get:

Can't declare scalar assignment in "my" at filename line 9, near ") =~"
($new_var = $old_var) =~ s/find_this/change_it_to_this/;

or is this what you wanted :-)

my $sgasizes="1223,456,23234,-343,3457,82222";
my $currsga;
($currsga) = $sgasizes =~ m/-(\d+)?/p;
print "SGA:$currsga";

SGA:343

Match a regular expression across multiple lines

I always forget this regex and it's sooo useful!

perl -00 -ne 'print "$1 - $2\n"  if /^"(\w+?)"\).*?RMAN_RECOVERY_WINDOW=(\d+)?/s' backup.ini

where backup.ini looks like this:

"SIANAP1")
EXP_ZIP_DUMPS="Y"
;;

"SICRMA3")
EXP_FLASHBACK="N"
RMAN_RECOVERY_WINDOW=5
RMAN_HOURS_TO_KEEP_ARCHIVES_ON_DISK=48
EXP_NUM_PARALLEL_WORKERS=16
;;

"SICRMA4")
RMAN_RECOVERY_WINDOW=10
RMAN_HOURS_TO_KEEP_ARCHIVES_ON_DISK=48
EXP_NUM_PARALLEL_WORKERS=5
;;

"SICRMP1")
RMAN_RECOVERY_WINDOW=15
;;

"SICRMP2")
RMAN_RECOVERY_WINDOW=20
;;

"SICRMQ2")
RMAN_RECOVERY_WINDOW=25
RMAN_HOURS_TO_KEEP_ARCHIVES_ON_DISK=48
;;

Using /s and /m modifiers in a regular expression

Tom Christiansen in his Perl Cookbook demonstrates the difference between these 2 confusing modifiers

$/ = //;            # paragraph read mode for readline access
while (<ARGV>) {
    while (m#^START(.*?)^END#sm) {  # /s makes . span line boundaries
                                    # /m makes ^ match near newlines
        print "chunk $. in $ARGV has <<$1>>\n";
    }
}

Match regular expression and assign to a variable in a single step

$started = $1 if $stmt =~ /Export started at (\d+)/;

or split directory and filenames (on Windows or Unix)

($dirname,$filename) = $fullname =~ m|^(.*[/\])([^/\]+?)$|;

or split a line into bits and assign the bits to variables

my ($host,$sid,$dbid,$timethen,$timesuccess,$recid,$stamp,$started,$ended,$size,$status,$type) = split (/\|/);

Perl ternary operator

Putting examples here as I keep forgetting the syntax/semantics! Theoretically it should be:

condition ? evaluate_if_condition_was_true : evaluate_if_condition_was_false

which to me means:

($type == 'ARCHIVELOG') ? $age_alert = $arc_alert : $age_alert = $job_alert;

but it's not like that, it's like this:

$age_alert = ($type == 'ARCHIVELOG') ?  $arc_alert : $job_alert;

and this

print "<td class=\"left\">"; print $created ne // ? scalar(gmtime($created)) : "&nbsp"; print "</td>";

Extract a value from a comma separated list of values in Perl

Suppose you need the 10th column …but only from the lines ending in 'detail'

/^(?:[^,]+,){9}([^,]+),(?:[^,]+,)*detail$/

or

$input =~ /detail$/ && my @fields = split(/,/, $input);

and print out the 10th element of @fields

Typical filter program (without needing to slurp)

Keep one of these here to save me looking it up all the time!

  - !/usr/bin/perl

use strict;
use warnings;

my $filename = "$ENV{TEMP}/test.txt";
open (my $input, '<', $filename) or die "Cannot open '$filename' for reading: $!";

my $count;

while ( my $line = <$input> ) {
    my @words = grep { /X/ } split /\b/, $line;
    $count += @words;
    print join(', ', @words), "\n";
}

print "$count\n";

__END__