Perl/Scripts

From Christoph's Personal Wiki
Revision as of 08:32, 8 September 2007 by Christoph (Talk | contribs) (Average numbers)

Jump to: navigation, search

The following is a compilation of useful one-line scripts for Perl. The original was compiled by Tom Christiansen, however, I have converted it into the wiki format and have added more examples (always adding more).

Perl one-liners

  • run contents of "my_file" as a program
perl my_file
  • run debugger "stand-alone"
perl -d -e 42
  • run program, but with warnings
perl -w my_file
  • run program under debugger
perl -d my_file
  • just check syntax, with warnings
perl -wc my_file
  • useful at end of "find foo -print"
perl -nle unlink
  • simplest one-liner program
perl -e 'print "hello world!\n"'
  • add first and penultimate columns
perl -lane 'print $F[0] + $F[-2]'
  • just lines 15 to 17
perl -ne 'print if 15 .. 17' *.pod
  • in-place edit of *.c files changing all foo to bar
perl -p -i.bak -e 's/\bfoo\b/bar/g' *.c
  • command-line that prints the first 50 lines (cheaply)
perl -pe 'exit if $. > 50' f1 f2 f3 ...
  • delete first 10 lines
perl -i.old -ne 'print unless 1 .. 10' foo.txt
  • change all the isolated oldvar occurrences to newvar
perl -i.old -pe 's{\boldvar\b}{newvar}g' *.[chy]
  • command-line that reverses the whole file by lines
perl -e 'print reverse <>' file1 file2 file3 ....
  • find palindromes
perl -lne 'print if $_ eq reverse' /usr/dict/words
  • command-line that reverse all the bytes in a file
perl -0777e 'print scalar reverse <>' f1 f2 f3 ...
  • command-line that reverses the whole file by paragraphs
perl -00 -e 'print reverse <>' file1 file2 file3 ....
  • increment all numbers found in these files
perl i.tiny -pe 's/(\d+)/ 1 + $1 /ge' file1 file2 ....
  • command-line that shows each line with its characters backwards
perl -nle 'print scalar reverse $_' file1 file2 file3 ....
  • delete all but lines between START and END
perl -i.old -ne 'print unless /^START$/ .. /^END$/' foo.txt
  • binary edit (careful!)
perl -i.bak -pe 's/Mozilla/Slopoke/g' /usr/local/bin/netscape
  • look for dup words
perl -0777 -ne 'print "$.: doubled $_\n" while /\b(\w+)\b\s+\b\1\b/gi'
  • command-line that prints the last 50 lines (expensively)
perl -e '@lines = <>; print @lines[ $#lines .. $#lines-50' f1 f2 f3 ...
  • using the ternary operator:
echo "|E..|"|perl -ne 'printf("%s\n",substr($_,1,1)=~/[A-Z]/?substr($_,1,1):"_");'
# prints "E" if that substr is A-Z
# else prints "_"

The tr/// operator

The "tr///" operator performs a substitution on the individual characters in a string.

  • Simple example:
#!/usr/bin/perl -w
use strict;
my $text = 'some cheese';
$text =~ tr/ce/XY/;
print "$text\n";
  • More examples:
$x =~ tr/a/b/;          # replace each "a" with a "b".
$x =~ tr/ /_/;          # convert spaces to underlines.
$x =~ tr/aeiou/AEIOU/;  # capitalise vowels.
$x =~ tr/79/97/;        # exchange "7" and "9".

The only characters that have special meaning to "tr///" are the backslash and the dash. The latter indicates a range of characters:

$x =~ tr/0-9/QERTYUIOPX/; # Digits to letters.
$x =~ tr/A-Z/a-z/;        # Convert to lowercase.

Actually, the slash also has a special meaning to "tr///". The slash is called the "delimiter", because it indicates the "limit" on the list of characters to substitute. However, we can use most kinds of punctuation in place of the slash. For example:

$x =~ tr!aeiou!AEIOU!;
$x =~ tr:aeiou:AEIOU:;

Note that we can also use parentheses, but the syntax changes a little because parentheses include the idea of containment:

$x =~ tr(aeiou)(AEIOU);
$x =~ tr<aeiou><AEIOU>;

The semantics (meaning) don't change; only the syntax (way of writing it) changes. But even though the delimiter is arbitrary, we still talk about it as "tr///".

"tr///" returns the number of replacements it made:

my $salary = '$1,000,000.00';   # Dollar sign: use single quote!
my $ego = ($salary =~ tr/0/0/); # Count the zeros in salary.

One more thing: "tr///" has an alias: "y///". This is to please users of sed, which uses the "y///" command do to basically what "tr///" does. In Perl, "tr///" and "y///" do exactly the same thing; use whichever you like. Remember: there is more than one way to do it (TIMTOWTDI).

$text =~ tr/0-9/A-J/;   # Convert digits to letters.
$text =~  y/0-9/A-J/;   # Does exactly the same thing.

Options

"tr///" can take the following options:

c   # complement (invert) the search-list.
d   # delete found but un-replaced characters.
s   # squash duplicate replaced characters.

These options are specified after the final delimiter, like this:

$x =~ tr/abc/xyz/s;    # Note the "s" at the end.
$x =~ tr(abc)(xyz)s;   # Same thing, but with parentheses.
$x =~ tr/abc/xy/ds;    # Multiple options.
# In the last case, the "z" is missing. You'll see why shortly.

In the last example, we specified both the "d" and the "s" options. The order of the options is not important (i.e., "sd"="ds").

  • Examples:
#!/usr/bin/perl -w
use strict;

##### The "s" option #####
my $text = 'good cheese';
$text =~ tr/eo/eu/s;
print "$text\n";
# Output is: gud chese

##### The "d" option #####
my $big = 'vowels are useful';
$big =~ tr/aeiou/AEI/d;
print "$big\n";
# The first three vowels are made uppercase.
# The other two, which have no replacement
# character, are deleted because of the "d".

Average numbers

A program that reads numbers and outputs the average. Here is one such program:

#!/usr/bin/perl -w
use strict;
my $line;
my $sum=0;
my $n=0;
while(defined($line=<STDIN>)){
  $sum+=$line;
  $n++;
}
my $average=$sum/$n;
print "The average is $sum/$n = $average\n";

External links