perl
perl is a handy language that's more powerful than shell programming, but less formal and time-consuming than C++.
It uses the same ideas of metacharacters and regular expressions that are used by grep, awk, and sed.
(For more about metacharacters, see my sed webpage.)
Example 1: cosmic.pl
This script looks in a C++ header file for a marker string, which is supplied at the command line;
(it takes the following forms: "sk1marker" "sk2marker" "sk3marker".)
Then the script finds the line containing the input string and deletes everything that is not a number or a space from that line.
Then it deletes leading space.
The split function takes a string as its first argument (" ") and a regular expression ($_) as its second argument.
It returns a list of values from the regular expression that are separated by the a space, which in this case, correspond to three numbers.
Like C, the array/list is numbered beginning with 0.
Last, the program adds the (three) numbers and prints their sum to the standard output.
#! /usr/bin/perl
#syntax: cosmic.pl skxmarker cosmic.h
$input = shift;
while (<>) {
if (/$input/) {
s/[^0-9 ]//g;
s/^ *//;
@nums = split (/ /,$_);
$answer = $nums[0] + $nums[1] + $nums[2];
print $answer
}
}
To define an array (w/o using split): @p3 = (46,78,67);
To define a multidimensional array: @test = ( [1,2], [3,4], [5,6] );
To define an array of arrays:
@t1 = (1,2);
@t2 = (3,4);
@test = (\@t1, \@t2);
Example 2: scramble.pl
This script reads in a file and spits out the lines in a random order.
Notice, that $#ARGV+1 is the equivalent of argc in C++.
Also notice that it goes down by one value, when you shift perform the shift command.
The dot operators concatenate strings.
The int() function converts floats to integers.
#! /usr/bin/perl
if($#ARGV+1 ==0 ) {print "syntax: scramble.pl filename outlines\n"; exit;}
$filename = shift;
$outlines = shift;
$nlines = `~ethrane/bin/lc.csh $filename`;
if($outlines > $nlines) {print "outlines > nlines\n"; exit;}
$x = 0;
while ($x < $nlines) {$array[$x] = 0; $x++;}
$x = 0;
while ($x < $outlines) {
$ok = 0;
$l = int(rand($nlines))+1;
while ($ok == 0) {
if($array[$l] == 0) {
$ok=1; $array[$l]=1;
open(file, $filename);
while() {if($.==$l) {print $_;}}
close(file);
}
$l++; if($l > $nlines) {$l += -$nlines;}
}
$x++;
}
Example 3: qclean.pl
This script sleeps for 10 seconds, then erases .log and .err files from a batch NQS submission before going back to sleep.
It runs for 3 hours or until NQS is idle.
To execute unix commands from within a perl script: system "ls";
To kill UNIX jobs:
# kill all open pine sessions
system 'killall', 'pine';
# open a new pine session
system "pine";
To set perl variables using unix commands: $test = `ls`;
Example 4: math.pl
Looks for the regular expression "Out.*" (from the Mathematica kernel.)
Deletes all other lines and converts output into C++ style scientific notation.
#! /usr/bin/perl
while (<>) {
if(/Out.*/){
s/Out\[.*\]= //;
s/ 10\n//;
print ($_,"E",$exp);
}
s/ *//;
$exp = $_;
}
Example 5: RunTheta.pl
In this example, we use a foreach loop to loop over muon energies.
We use the commands open and close to read an input file and write to an output file.
To open an input file:
open(input, "./input.dat");
#multiply each line by 3 and print the result.
while (<input>) {print $_*3;}
close(input);
To open an output file:
open(output, ">>./output.dat");
print output ($x,"\n");
close(output);
Example 6: Part2.pl
Loop over files that end in ".dat" with a foreach loop.
Use the command chomp to remove a trailing line break.
To loop over files in the directory "tmp/" that end in ".dat": foreach $file (<./tmp/*.dat>) { ... }
Another way to examine the contents of a directory:
opendir(DIR, "./tmp");
@list = readdir(DIR);
closedir(DIR);
foreach $file (@list) { ... }
Does a directory exist? if (-d $dirname) { ...
To delete the trailing line break from the variable $x: chomp($x);
Example 7: sort_bib.pl
Change the order of entries in a bibtex file so that the last entries come first and the first entries come last.
#! /usr/bin/perl5.30
$i = -1;
while (<>) {
# if the line defines a shortcut (string), it is not a bibtex entry
if ($_ =~ m/\@String.*/) {print "$_";}
# if the line begins with % it is a comment, not a bibtex entry
elsif ($_ =~ /\%.*/) {print $_;}
# skip over white space
elsif (/^\s*$/) {}
else {
# bibtex entries begin with @
if ($_ =~ m/\@.*/) {
$i++;
$entries[$i] = $_;
}
# still part of the same bibtex entry
else {
$entries[$i] = $entries[$i].$_;
}
}
}
# create extra space between strings and bib entries
print "\n";
# print entries in reverse order
for ($j=$i; $j>=0; $j--) {
print $entries[$j]."\n";
}
# print bib entries in order with numbers (testing only)
#for ($j=0; $j<=$i; $j++) {
# print "########### $j ###########\n";
# print $entries[$j];
#}
Example 8: Prepare a bib entry for upload to RMS: sort_bib_arc.pl.
To substitute/replace a string in a perl variable:
$x = "The height is zpos.\n"
$x =~ s/zpos/-100/;
print $x;
The height is -100.
To access UNIX environmental variables from Perl: $out = "$ENV{'workdir'}";
To test if a variable contains a certain regular expression: if($varb =~ m/[0-9]\.5/) {print $varb;} ("m" is for "match.")
The line number in the current open file: $.
or alternatively:
open $fh, "findjobs.out";
my @lines = <$fh>;
print "$lines[3]"
To create a sub-function:
sub short {
$_[0] = int($_[0])."." #$_[0] is the 0th argument of short().
}
To use a trigonmetric function:
use Math::Trig;
print acos(-1);
a for loop: for ($i=0; $i<12; $i++) {$dtheta += rand();}
To compare the values of two strings: if($table eq "swift_grb_table.dat")
To remove extra white space: $_ =~ s/\s+/ /g;
To remove ^M characters created by Microsoft Excel: $_ =~ s/\015/\n/g;
To open two input files at once:
open(input1, "input1.dat");
while($x=<input1>){
open(input2, "input2.dat");
while($y=<input2>){
...
or better yet: while ($q=<file>,$n=<nfile>) {
To call perl from within a csh script:
setenv fres `perl -e '{ \
$fres = sqrt(13);\
print $fres;\
}'`
To access environmental variables in perl: $x = $ENV{'PATH'};
sort: @sorted = sort @array;
array size: $size = $#array;
numerical precision: $x==sprintf("%.3f",$x);
open two files at once:
open(trial100, "./trial100.list");
open(tmp,">tmp.txt");
while($x = ){ # $x is like $_
Back to Resources