lecture
in color
lin08% man perl (lists lots of other man pages)
lin08% perldoc perl (documents internal features as well)
#! /var/local/couch/bin/perl print "Hello\n";
#! /var/local/couch/bin/perl: location of perl interpreter
#!: this is a script: must be first two characters of file!
/var/local/couch/bin/perl: interpreter for script.
/usr/bin/perl for best results.
print "Hello\n";
\n is carriage return (as in C).
chmod ugo+x helloor
chmod 755 helloto make it executable so it'll run. After that, just type
helloon
lin08 through lin10 to run it.
comp150ppp.eecs.tufts.edu
mezzo.eecs.tufts.edu first, then
to the machine.
mezzo.eecs.tufts.edu
$foo: a scalar variable (one thing)
@foo: an array of things;
each one is $foo[$i] for some integer $i.
%foo: an associative array of things,
$foo{'hoho'} is the thing associated with the string
'hoho'.
foo: lack of prefix indicages a filehandle.
&foo: a subroutine call.
*foo: a glob. Embodies all meanings of a
name, like a Lisp 'symbol'.
$foo, @foo, %foo, foo
and &foo represent different things!
$foo[10000]='hi'; implicitly creates
$foo[0] ... $foo[9999]!
$foo, @foo, %foo, &foo, foo are all distinct.
$foo is the scalar foo, $foo[5] is an element of the array @foo.
@foo[5] is the array containing just element 5 of @foo!
@foo[5..7] is the subarray of @foo containing just elements $foo[5] to $foo[7].
$foo{'hoho'} is the element corresponding to 'hoho' in %foo.
$a > $b compares $a and $b
as numbers.
$a gt $b compares $a and $b
as strings.
$a + $b sums $a and $b as numbers.
$a . $b concatenates $a and $b as strings.
> >= == <= < !=: numeric comparisons
$a <=> $b (numbers) is
$a<$b
$a==$b
$a>$b
$a . $b concatenates $a and $b (like JavaScript '+').
gt,ge,eq,le,lt,ne: String comparisons in alphabetical order
$a cmp $b (strings) is
$a lt $b
$a eq $b
$a gt $b
12 lt 123
24 gt 123
$i=1; $j = "i+1 is " . ($i+1);
works exactly as you'd expect.
1 for TRUE
undef for FALSE
undef: the undefined value
defined $foo is 1 if $foo
has a value, undef if not!
'string': a constant string.
'$foo/bar::whatever\n' is just that, literally.
'\n' is just \n, not carriage return.
"string": variable substitutions are done; result is used.
"\t\n" has the value consisting of a tab character
followed by a newline character.
$foo='bar'; $goo="this $foo is for you\n"
makes $goo have the value
"this bar is for you<newline>"
`string` executes string as a UNIX command,
and its value is the resulting output from the command!
`w` runs the w command, returns a list of users!
% which w /usr/bin/wUse
`/usr/bin/w` for best results!
contents of perl_basics/e02.pl... #! /var/local/couch/bin/perl # Basics of scalar variables # this example describes properties of numbers and strings $foo = 'hello'; # part 1: kinds of strings print "01 foo=$foo\n"; # string substitution into double quotes print "\n"; # carriage return print '02 foo=$foo\n'; # no string substitution into single quotes print "\n"; # this makes the previous line show up, no \n on it print "\n"; print "03\n"; print `w`; # backquotes execute a unix command print "\n"; # part 2: string operations and numbers print "04 test string concatenation: \n"; print "this " . "is " . "a " . "test.\n"; print "\n"; print "05 test numeric values of strings:\n"; $foo = '123'; $bar = $foo + 0; print "06 $foo + 0 = $bar\n"; $foo = '123hello'; $bar = $foo + 0; print "07 $foo + 0 = $bar\n"; $foo = 'hello'; $bar = $foo + 0; print "08 $foo + 0 = $bar\n"; ...end of perl_basics/e02.pl
contents of perl_basics/e02.pl.out... 01 foo=hello 02 foo=$foo\n 03 3:49pm up 6 days, 23:41, 4 users, load average: 0.18, 0.71, 0.62 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT jco pts/0 dhcp-224 12:00pm 20:25 0.20s 0.20s -bash couch pts/1 conmoto 3:29pm 2.00s 0.28s 0.01s /var/local/couc couch pts/2 blackhole 2:29pm 54:01 0.21s 0.21s -tcsh jco pts/3 dhcp-224 3:27pm 21:36 0.08s 0.08s -bash 04 test string concatenation: this is a test. 05 test numeric values of strings: 06 123 + 0 = 123 07 123hello + 0 = 123 08 hello + 0 = 0 ...end of perl_basics/e02.pl.out
@foo: an array
$#foo: top element index currently in array(changes as array expands)
(top element is $foo[$#foo])
$[: what element arrays start at (normally 0) but you can change it if you dare!
@foo[1..3,7]: a smaller array consisting of $foo[1], $foo[2],$foo[3]
and $foo[7]
(1, 4, 7): an array literal.
.. allows creation of lots of useful
arrays:
(1..3) is (1,2,3)
('a'..'f') is ('a','b','c','d','e','f').
push(@foo,2): put 2 at the top of an array.
$val = pop(@foo): get an element off the top.
$val = shift(@foo): get an element off the bottom.
unshift(@foo,3): put an element onto the bottom.
scalar(@foo): number of elements in the array @foo (!)
@a = (1,2,'hoho',(5, 'haha'));means
@a=(1,2,'hoho',5,'haha');(arrays fold flat when nested)
@b = (@a, 'jojo', @a[1..2]);means
@b=(1,2,'hoho',5,'haha','jojo',2,'hoho')
split: convert a string into an array of substrings
split(/\s/, 'This is a sentence')
becomes ('This', 'is', 'a', 'sentence')
join: convert an array into a string.
join(':', ('this','is','a','test'))
is 'this:is:a:test'
join(':',split(/\s/,' a bad one'))
is :a:bad:one
Split's first array location will be empty if appropriate.
split's first argument is /something/,
then it's a regular expression to be matched against
(more details later).
contents of perl_basics/e05.pl...
#! /var/local/couch/bin/perl
# test join and split
print "01 split 'this is a test' at ' 's\n";
@a = split(' ','this is a test');
foreach $a (@a) { print "\@a contains '$a'\n"; }
print "\n";
print "02 split name:password:uid:gid by ':'\n";
@a=split(':','name:password:uid:gid');
foreach $a (@a) { print "\@a contains '$a'\n"; }
print "\n";
print "03 test join of ('a','b',1,271,'hoho')\n";
$a = join(' ',('a','b',1,271,'hoho'));
print "join is $a\n\n";
print "04 test join of ('a','b',1,271,'hoho') using ':'\n";
$a = join(':',('a','b',1,271,'hoho'));
print "join is $a\n\n";
...end of perl_basics/e05.pl
contents of perl_basics/e05.pl.out...
01 split 'this is a test' at ' 's
@a contains 'this'
@a contains 'is'
@a contains 'a'
@a contains 'test'
02 split name:password:uid:gid by ':'
@a contains 'name'
@a contains 'password'
@a contains 'uid'
@a contains 'gid'
03 test join of ('a','b',1,271,'hoho')
join is a b 1 271 hoho
04 test join of ('a','b',1,271,'hoho') using ':'
join is a:b:1:271:hoho
...end of perl_basics/e05.pl.out
contents of perl_basics/people.pl...
#! /var/local/couch/bin/perl
$people = `w`;
@people = split("\n",$people);
$banner = shift (@people);
$baner2 = shift (@people);
foreach $person (@people) {
($login,$tty,$from,$when,@other) = split(/\s+/,$person);
print "$login logged in at $when from $from\n";
}
...end of perl_basics/people.pl
split: split a string into an array.
\n: split at carriage returns.
shift(@array): remove first element of an array,
"shift" all others over to match.
/\s+/: split at one or more whitespace characters.
w is:
contents of perl_basics/people.pl.wout... 3:30pm up 6 days, 23:23, 4 users, load average: 0.95, 0.45, 0.17 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT jco pts/0 dhcp-224 12:00pm 1:54 0.78s 0.29s make couch pts/1 conmoto 3:29pm 2.00s 0.26s 0.02s w couch pts/2 blackhole 2:29pm 35:30 0.21s 0.21s -tcsh jco pts/3 dhcp-224 3:27pm 3:05 0.08s 0.08s -bash ...end of perl_basics/people.pl.woutthen the output of
people.pl is
contents of perl_basics/people.pl.out... jco logged in at 12:00pm from dhcp-224 couch logged in at 3:29pm from conmoto couch logged in at 2:29pm from blackhole jco logged in at 3:27pm from dhcp-224 ...end of perl_basics/people.pl.out
something.cgi.
Content-type: text/html\n\n before anything else.
contents of perl_basics/people.cgi...
#! /var/local/couch/bin/perl
$harass='couch';
print "Content-type: text/html\n\n<html><body>\n";
$people = `w`;
@people = split("\n",$people);
foreach $person (@people) {
($login,$tty,$from,$when,@other) = split(/\s+/,$person);
if ($login eq $harass) {
print "<h1>$login logged in at $when from $from</h1>\n";
$found = 1;
}
}
if (!$found) {
print "<h1>$harass isn't around! Try later!</h1>\n";
}
print "</body></html>\n";
...end of perl_basics/people.cgi
Try this out!
scalar(@foo): scalar number of elements
(@foo): the array itself (parens force array context).
$i = @foo;: scalar context, assigns length of array to $i ($i = scalar(@foo))
@i = @foo;: array context, assigns whole array to array @i.
%i = @foo;: array context, assigns attribute/value pairs.
%i = ('a','b','c','d'); means $i{'a'}='b'; $i{'c'}='d';
%i = ('a' => 'b', 'c' => 'd');
but it means the same thing as
%i = ('a', 'b', 'c', 'd');
contents of perl_basics/e03.pl...
#! /var/local/couch/bin/perl
# Arrays
print "01 basic iteration over an array\n";
@a = (1,2,"ho",4);
foreach $thing (@a) {
print "\$thing = $thing is in \@a\n";
}
print "\n";
print "02 numbering elements in an array\n";
$nelems = @a;
print "\@a has $nelems elements\n\n";
print "03 iterating over elements in an array by number\n";
for ($i=0; $i<@a; $i++) {
print "element $i of \@a is $a[$i]\n";
}
print "\n";
print "04 printing \@a: @a\n";
print "05 initializing arrays\n";
print '@a=(1,2,(4,5),(\'ho\', (\'ha\')))' . "\n";
@a=(1,2,(4,5),('ho', ('ha')));
print "now \@a is @a\n";
print "06 printing an array in array notation\n";
print "\@a=(" . join(',',@a) . ")\n\n";
print "07 push(\@a,'hello')\n";
push(@a,'hello'); # same as @a=(@a,'hello');
push(@a,'hello');
print "\@a=(" . join(',',@a) . ")\n\n";
print "08 $a=pop(\@a)\n";
$a=pop(@a); # same as $a = $a[$#a]; $#a--;
print "\$a=$a, \@a=(" . join(',',@a) . ")\n\n";
print "09 \$a = shift(\@a)\n";
$a = shift(@a);
print "\$a=$a, \@a=(" . join(',',@a) . ")\n\n";
print "10 unshift(\@a, 'hu')\n";
unshift(@a,'hu');
print "\@a=(" . join(',',@a) . ")\n\n";
...end of perl_basics/e03.pl
contents of perl_basics/e03.pl.out...
01 basic iteration over an array
$thing = 1 is in @a
$thing = 2 is in @a
$thing = ho is in @a
$thing = 4 is in @a
02 numbering elements in an array
@a has 4 elements
03 iterating over elements in an array by number
element 0 of @a is 1
element 1 of @a is 2
element 2 of @a is ho
element 3 of @a is 4
04 printing @a: 1 2 ho 4
05 initializing arrays
@a=(1,2,(4,5),('ho', ('ha')))
now @a is 1 2 4 5 ho ha
06 printing an array in array notation
@a=(1,2,4,5,ho,ha)
07 push(@a,'hello')
@a=(1,2,4,5,ho,ha,hello,hello)
08 =pop(@a)
$a=hello, @a=(1,2,4,5,ho,ha,hello)
09 $a = shift(@a)
$a=1, @a=(2,4,5,ho,ha,hello)
10 unshift(@a, 'hu')
@a=(hu,2,4,5,ho,ha,hello)
...end of perl_basics/e03.pl.out
if (expr) {statements} else {statements}
while (expr) {statements}
# weird construction # equivalent normal one
unless (expr) {statements} # if (!expr) { statement; }
statement if expr; # if (expr) { statement; }
statement unless expr; # if (!expr) { statement; }
expr || statement; # if (!expr) { statement; }
expr or statement; # if (!expr) { statement; }
expr && statement; # if (expr) { statement; }
expr and statement; # if (expr) { statement; }
open(FILE,"</etc/motd") or die "can't open /etc/motd";
open works, it returns 1, so the die
isn't called.
open fails, it returns undef, so the die
executes and kills the program.
if ($i>0) { print "good\n"; }
print "good\n" if $i>0;
$i>0 && print "good\n";
$i>0 and print "good\n";
unless ($i>0) { print "bad\n"; }
print "bad\n" unless $i>0;
$i>0 || print "bad\n";
$i>0 or print "bad\n";
$i=0; while ($i<10) { print "$i\n"; }
for ($i=0; $i<10; $i++) { print "$i\n"; }
contents of perl_basics/e04.pl...
#! /var/local/couch/bin/perl
# Basic control flow
print "01 test if statements\n";
# should only report that if works
if (1) {
print "if works\n";
} else {
print "if doesn't work\n";
}
if (0) {
print "else doesn't work\n";
} else {
print "else works\n";
}
# should only report that if works
print "if works\n" if 1;
print "if doesn't work\n" if 0;
print "unless works\n" unless 0;
print "unless doesn't work\n" unless 1;
# should only report that && works(!)
1 && print "&& works\n";
0 && print "&& doesn't work\n";
# should only report that || works(!)
0 || print "|| works\n";
1 || print "|| doesn't work\n";
print "02 illustrate while\n";
$i=0;
while ($i<10) { print "$i "; $i++; }
print "\n\n";
...end of perl_basics/e04.pl
contents of perl_basics/e04.pl.out... 01 test if statements if works else works if works unless works && works || works 02 illustrate while 0 1 2 3 4 5 6 7 8 9 ...end of perl_basics/e04.pl.out
foreach $thing (@array) {
# do something for each element of @array
}
while (($key,$value) = each %stuff) {
# do something with key-value pairs
# playback order is random
# very efficient
}
$_: result of last operation
$1-$9: result of last pattern match
@_: arguments to subroutine call
$stuff = <STDIN> while (<STDIN>) { print $_; } @stuff = (<STDIN>); @stuff, parsed by lines.
<STDIN>: one line of input (in scalar context)
(<STDIN>): in array context, whole input to EOF
contents of perl_basics/e06.pl...
#! /var/local/couch/bin/perl
while (<STDIN>) { print };
...end of perl_basics/e06.pl
STDIN,
then prints the same thing.
$_ of <STDIN>
is also the implicit input of print.
print "ho\n";
print STDERR "ho\n"; # to standard error
open(IN,"<junk") || die "can't open junk"; junk for reading.
while (<IN>) { print $_; } close(IN) || die "can't close junk"; open(OUT,">out") || die "can't write to out"; out for writing.
print OUT "hello there\n"; OUT.
close(OUT) || die "can't close out";
STDIN: standard input
STDOUT: standard output
STDERR: standard error
ARGV: contents of files listed on
the command line, or STDIN, if none!
(very handy)
while (<ARGV>) { print; }
does the same thing as the UNIX cat command; it concatenates
all files on the command line and prints them out!
while ($thing=<ARGV>) { print $thing; }
or as
while (<ARGV>) { print $_; }
because the "last result" of <ARGV> is the implicit
variable $_!
contents of perl_basics/e07.cgi...
#! /var/local/couch/bin/perl
print "Content-type: text/html\n\n";
print "<pre>\n";
open (IN,"<e06.pl") || die "can't open file";
while (<IN>) { s/&/\&/g; s/</\</g; s/>/\>/g; print; }
print "</pre>\n";
...end of perl_basics/e07.cgi
$i =~ /foo/ : tests whether $i contains the substring 'foo'
$i =~ s/foo/bar/ : replace first instance of foo with bar in $i
$i !~ /foo/ : tests whether $i doesn't contain the substring 'foo'
while (<ARGV>) { print if $_ !~ /hello/; }
prints every line of every file listed on the command line that doesn't
contain the word "hello"!
$pattern = shift @ARGV;
while (<ARGV>) { print if $_ =~ /$pattern/; }
does pretty much what the UNIX command grep does:
it takes its first argument as a pattern to match in further files.
E.g., if this is put into a file pg then
pg foo junkprints all lines containing '
foo' in the file junk
$pattern = shift @ARGV;
while (<ARGV>) { print if /$pattern/; }
<ARGV> has an implicit output $_.
$_ is an implicit input to /$pattern/.
$_ is also an implicit input to print!
/foo/: a pattern
. - match any character
^ - beginning of line/string
$ - end of string
[123] - match one of characters '1', '2', or '3' here.
[^123] - match anything but characters '1', '2', '3' here
* - match 0 or more occurrences of the preceding form
a*: 0 or more a's
.*: 0 of more of any character
[0-9]*: 0 or more digits.
[a-zA-Z]*: 0 or more alphabetic characters,
upper or lower case.
+ - match one or more occurrences of the preceding form,
otherwise like *.
? - match 0 or 1 occurrences of the preceding form,
otherwise like *
(...) - enclose something that'll be used as a variable later.
variables are \1,\2,\3 INSIDE replacement patterns, $1,$2,$3
OUTSIDE the pattern (in normal perl code).
| - alternate between options in a group, e.g. (foo|bar) matches
either foo or bar.
{2} - match two occurrences of preceding thing
{2,3} - match between two and three occurrences of preceding thing
a{2,3} - aa or aaa
(foo){2,3} - foofoo or foofoofoo
\&, \^, \$, \[, \], \*, \+, \?, \(, \), : match literal characters
/^foo/: anything beginning with the characters 'foo'
/foo$/: anything ending with the characters 'foo'
/^.*$/: matches anything at all.
/(-?[1-9][0-9]*)/: matches anything containing a number,
binds the largest number it can to a variable $1 (if found)
contents of perl_basics/e09.pl...
#! /var/local/couch/bin/perl
# prints out all lines containing numbers.
while (<STDIN>) {
print $_ if $_ =~ /[0-9]/;
}
...end of perl_basics/e09.pl
contents of perl_basics/e10.pl...
#! /var/local/couch/bin/perl
# prints out all lines containing numbers.
while (<STDIN>) { print if /[0-9]/; }
...end of perl_basics/e10.pl
contents of perl_basics/index.pl...
#! /var/local/couch/bin/perl
$line=1;
while (<ARGV>) {
@words = split;
foreach $word (@words) {
# $a .= $b means $a = $a . $b
$index{$word} .= ',' if defined $index{$word};
$index{$word} .= $line;
}
$line++;
}
# vvvvvvvvvvvvvvvv put into alpha order.
# vvvvvvvvvvv indices (words) for the array
# vvvvvv associative array
@words = sort keys %index; # get all words in sorted order
foreach $word (@words) {
print "$word: $index{$word}\n";
}
...end of perl_basics/index.pl
contents of perl_basics/index.in... This is a test. This is another test. This is still yet another test. ...end of perl_basics/index.in(via
index.pl <index.in >index.out)
contents of perl_basics/index.out... This: 1,2,3 a: 1 another: 2,3 is: 1,2,3 still: 3 test.: 1,2,3 yet: 3 ...end of perl_basics/index.out
() actually bind variables
during the matching process.
$1 to $9 correspond to the
contents matched by the patterns inside the
first through ninth opening parens.
$a = "199 20 3"; $a =~ /([0-9]+) ([0-9]+) ([0-9]+)/;
$1 is 199, $2 is 20,
and $3 is 3.
contents of perl_basics/e11.pl...
#! /var/local/couch/bin/perl
# print the first number in each line
while (<STDIN>) {
# vvvvvvvvvvvvv pattern for $1
# vvvvvvvvvvv pattern for a number
if ($_ =~ /([1-9][0-9]*)/) { print "$1\n"; }
if ($_ =~ /(^|\s+)([1-9][0-9]*)($|\s+)/) {print "$2 is really a number.\n";}
# ^^^^^^^ ^^^^^^^ delimited by spaces on both sides
}
...end of perl_basics/e11.pl
lecture
in color