Defindit Docs and Howto Home
title:Perl one liners
description:Perl one line scripts run from the command line or used in piped commands in the shell.
keywords:perl,regexp,regex,regular,expression,sed,awk,bash,sh


-e is execute this string as Perl
-n is loop through the input, no printing of the input lines
-p is loop through the input, print the input lines as well as any ouput.


Example 1.0
-----------

Use "find" to exec the "file" command and use a perl one line script
to print the file name which chmod uses (via the backticked "find"
command) to make the file permissions +x. Note that "find" is inside
backticks. The Perl oneliner is in a single quoted (aka tick) string
which contains a print statement with a double quoted string.

chmod -v +x `find ./ -exec file {} \; | grep executable | perl -ne 'm/^(.*?):/; print "$1\n" ' `



Example 1.1
-----------

The "grep executable" could be moved into the Perl regex as well, but
then the regex must be wrapped in a if statement to prevent $1 from
printing for every line of input. The regex is slightly more complex
than the example above. Remember, $1 retains its value between
iterations.

chmod -v +x `find ./ -exec file {} \; | perl -ne 'if (m/^(.*?):.*executable/){ print "$1\n"; } '`


Example 1.2
-----------

There is also the tr command (not Perl, but sometimes handy):

Here are rot13 and un-rot13 examples:
tr A-Za-z N-ZA-Mn-za-m < good.txt > gibberish.txt
tr N-ZA-Mn-za-m A-Za-z  < gibberish.txt > good.txt


Example 1.3
-----------

Oddly, the command below works, due to the DWIMish nature of Perl (DWIM = Do What I
Mean). Or due to the fact that every line of the file c040721c03.txt
has one and only one match.

cat txt_files/c040721c03.txt  | perl -ne 'm/\s+([A-Z\*\?]+)\s+/; print "$1\n" '

This is probably robust.

cat txt_files/c040721c03.txt  | perl -ne 'if (m/\t+([A-Z\*\?]+)\s+/s) { print ".$1.\n"} '  | less


The variante below is interesting since it will search for "peptide-like" strings multiple times per line. 
It finds all kinds of garbage.

cat txt_files/c040721c03.txt  | perl -ne 'while (m/\s+([A-Z\*\?]+)\s+/g) { print ".$1.\n"} '  | less



Example 1.4
-----------

# Use the e switch at the end of the regex to eval the right side of the regex.
# The eval is necessary when using a Perl function as below
cat oldfile | perl -pe 's/(\d+)_/sprintf("%2.2d_",$1)/e' > newfile



Example 1.5
-----------

# A simple example that changes /session_lib to /geoss_session_lib throughout a file.
# This is a double bash command, and the second half renames the .new file.
# To make this work over multiple files I created a text file of shell commands
# using Emacs macros. It's crude but simpler than trying to get some combination of "find" and "xargs"
# to do it in a single bash command. I use "find" to generate the original list of files
# that I modify with the Emacs macro. 

cat ./bin/geoss_adduser.pl | perl -pe 's/\/session_lib/\/geoss_session_lib/' > ./bin/geoss_adduser.pl.new; mv ./bin/geoss_adduser.pl.new ./bin/geoss_adduser.pl



Example 1.6
-----------

# A related utility is xargs.
egrep -ho "http://.*a.jpg" file*.html | xargs wget



Example 1.7 (and variants)
--------------------------

# test regex 04-01* to 02-22* before calling with rename()
find -exec perl -e '$new=$ARGV[0]; $new =~ s/.\/04\-01(.*)/02\-22$1/; print "$new\n";' {} \;


# Another test, and alternate implementation
find -exec perl -e '$ARGV[0] =~ m/.\/04\-01(.*)/; print "02\-22$1\n"; ' {} \;


# regex rename 02-22* 04-01* and visa-versa.
find -exec perl -e '$new=$ARGV[0]; $new =~ s/.\/02\-22(.*)/04\-01$1/; rename($ARGV[0],$new);' {} \;


find -exec perl -e '$new=$ARGV[0]; $new =~ s/.\/04\-01(.*)/02\-22$1/; rename($ARGV[0],$new);' {} \;


# regex rename 02-22* to "04-01*"
find -exec perl -e '$new=$ARGV[0]; $new =~ s/.\/02\-22(.*)/\"04\-01$1\"/; rename($ARGV[0],$new);' {} \;


# regex rename "*" to *
find -exec perl -e '$new=$ARGV[0]; $new =~ s/\"//g; rename($ARGV[0],$new);' {} \;