perl study note

I'm studing perl language , This is just a note when I read a book named learning Perl . for remember and check back. I will frequently change it until I read over that book.
What Does Perl  Stand For?
Perl is sometimes called the ¡°Practical Extraction and Report Language,¡± although it
has also been called a Pathologically Eclectic Rubbish Lister,
What Is CPAN?
CPAN is the Comprehensive Perl Archive Network, your one-stop shop for Perl.
you might use a shebang line that
finds perl for you:
#!/usr/bin/env perl
Table 2-1. Double-quoted string backslash escapes
Construct Meaning
/n Newline
/r Return
/t Tab
/f Form-feed
/b Backspace
/a Bell
/e Escape (ASCII escape character)
/007 Any octal ASCII value (here, 007 = bell)
/x7f Any hex ASCII value (here, 7f = delete)
/cC A “control” character (here, Control-C)
// Backslash
/” Double quote
/l Lowercase next letter
/L Lowercase all following letters until /E
/u Uppercase next letter
/U Uppercase all following letters until /E
/Q Quote nonword characters by adding a backslash until /E
/E End /L, /U, or /Q
To run your program with warnings turned on
$ perl -w my_program
#!/usr/bin/perl -w
#!/usr/bin/perl
use warnings;
you can get a longer
description of the problem with the diagnostics pragma.
#!/usr/bin/perl
use diagnostics;
$ perl -Mdiagnostics ./my_program
Table 2-2. Associativity and precedence of operators (highest to lowest)
Associativity Operators
left parentheses and arguments to list operators
left ->
++ -- (autoincrement and autodecrement)
right **
right / ! ~ + - (unary operators)
left =~ !~
left * / % x
left + - . (binary operators)
left << >>
named unary operators (-X filetests, rand)
< <= > >= lt le gt ge (the “unequal” ones)
== != <=> eq ne cmp (the “equal” ones)
left
&
left | ^
left &&
left ||
.. ...
right ?: (ternary)
right = += -= .= (and similar assignment operators)
left , =>
list operators (rightward)
right not
left and
left or xor
Table 2-3. Numeric and string comparison operators
Comparison Numeric String
Equal == eq
Not equal != ne
Less than < lt
Greater than > gt
Less than or equal to <= le
Greater than or equal to >= ge
the last element index is $#rocks
$end = $#rocks;                  # 99, which is the last element's index
$number_of_rocks = $end + 1;     # okay, but you'll see a better way later
$rocks[ $#rocks ] = 'hard rock'; # the last rock
$rocks[ −1 ] = 'hard rock';      # easier way to do that last example
$dead_rock = $rocks[−100];       # gets 'bedrock'
$rocks[ −200 ] = 'crystal';      # fatal error!
uses the .. range operator,
That
operator creates a list of values by counting from the left scalar up to the right scalar
by ones. For example:
(1..5)
# same as (1, 2, 3, 4, 5)
(1.7..5.7)
# same thing - both values are truncated
(5..1)
# empty list - .. only counts "uphill"
(0, 2..6, 10, 12) # same as (0, 2, 3, 4, 5, 6, 10, 12)
($m..$n)
# range determined by current values of $m and $n
(0..$#rocks)
# the indices of the rocks array from the previous section
qw stands for “quoted words” or “quoted by whitespace,”
qw( fred barney betty wilma dino ) # same as above, but less typing
you can’t use /n or $fred
inside a qw list as you would in a double-quoted string
swap two variables’ values in Perl:*
($fred, $barney) = ($barney, $fred); # swap those values
($betty[0], $betty[1]) = ($betty[1], $betty[0]);
The pop operator takes the last element off of an array and returns it:
@array = 5..9;
$fred
= pop(@array);
$barney = pop @array;
pop @array;
# $fred gets 9, @array now has (5, 6, 7, 8)
# $barney gets 8, @array now has (5, 6, 7)
# @array now has (5, 6). (The 7 is discarded.)
adds an element (or a
list of elements) to the end of an array:
push(@array, 0);
push @array, 8;
push @array, 1..10;
@others = qw/ 9 0 2 1
push @array, @others;
#
#
#
0
#
@array
@array
@array
/;
@array
now has (5, 6, 0)
now has (5, 6, 0, 8)
now has those ten new elements
now has those five new elements (19 total)
The shift and unshift Operators
@array = qw# dino fred barney #;
$m = shift(@array);
# $m gets "dino", @array now has
$n = shift @array;
# $n gets "fred", @array now has
shift @array;
# @array is now empty
$o = shift @array;
# $o gets undef, @array is still
unshift(@array, 5);
# @array now has the one-element
unshift @array, 4;
# @array now has (4, 5)
@others = 1..3;
unshift @array, @others; # @array now has (1, 2, 3, 4, 5)
("fred", "barney")
("barney")
empty
list (5)
The foreach loop steps through a list of values, executing one iteration
(time through the loop) for each value:
foreach $rock (qw/ bedrock slate lava /) {
print "One rock is $rock./n"; # Prints names of three rocks
}
The control variable is not a copy of the list element—it actually is the list element.
That is, if you modify the control variable inside the loop, you’ll be modifying the
element itself, 
$_. This is (mostly) just like any other scalar variable, except
for its unusual name. For example:
foreach (1..10) { # Uses $_ by default
print "I can count to $_!/n";
}
The reverse operator takes a list of values (which may come from an array) and returns
the list in the opposite order.
@fred=6..10;           
@barney=reverse(@fred);# gets 10, 9, 8, 7, 6
@wilma=reverse 6..10;  # gets the same thing, without the other array
@fred=reverse @fred;   # puts the result back into the original array
The sort operator
@rocks=qw/ bedrock slate rubble granite /;
@sorted=sort(@rocks);# gets bedrock, granite, rubble, slate
@back=reverse sort @rocks; # these go from slate to bedrock
@rocks=sort @rocks;# puts sorted result back into @rocks
@numbers=sort 97..102;# gets 100, 101, 102, 97, 98, 99
Since undef is a scalar value, assigning undef to an array doesn’t clear the array. The
better way to do that is to assign an empty list.*
@wilma = undef; # OOPS! Gets the one-element list (undef)
# which is not the same as this:
@betty = ( );# A correct way to empty an arrays
you can use the fake function scalar. It’s not a true function because it just tells
Perl to provide a scalar context:
@rocks = qw( talc quartz jade obsidian );
print "I have ", scalar @rocks, " rocks!/n"; # Correct, gives a number
To define your own subroutine, use the keyword sub
sub marine {
$n += 1; # Global variable $n
print "Hello, sailor number $n!/n";
}
Invoking a Subroutine
&marine; #says Hello, sailor number 1!
Return Values
sub sum_of_fred_and_barney {
print "Hey, you called the sum_of_fred_and_barney subroutine!/n";
$fred + $barney; # That's the return value
}
But suppose you added
another line to the end of the code, like this:
sub sum_of_fred_and_barney {
print "Hey, you called the sum_of_fred_and_barney subroutine!/n";
$fred + $barney; # That's not really the return value!
print "Hey, I'm returning a value now!/n";
# Oops!
}
The use of parameter in subroutine
sub max {
# Compare this to &larger_of_fred_or_barney
if ($_[0] > $_[1]) {
$_[0];
} else {
$_[1];
}
}
you can create private variables called lexical variables
at any time with the my operator:
sub max {
my($m, $n);
# new, private variables for this block
($m, $n) = @_;
# give names to the parameters
if ($m > $n) { $m } else { $n }
}
or
my($m, $n) = @_; # Name the subroutine parameters
Of course, you can use my to create new, private arrays as well:
my @phone_number;
To tell Perl that you’re ready to be more restrictive, put the use strict pragma at the
top of your program (or in any block or file where you want to enforce these rules):
use strict; # Enforce some good programming rules
The return operator immediately returns a value from a subroutine:
my @names = qw/ fred barney betty dino wilma pebbles bamm-bamm /;
my $result = &which_element_is("dino", @names);
sub which_element_is {
my($what, @array) = @_;
foreach (0..$#array) { # indices of @array's elements
if ($what eq $array[$_]) {
return $_;
# return early once found
}
}
−1;
# element not found (return is optional here)
}
if Perl’s internal compiler has already seen the subroutine definition, that’s generally
okay
my @cards = shuffle(@deck_of_cards); # No & necessary on &shuffle
sub division { # Divide first param by second
$_[0] / $_[1]; 
my $quotient = division 355, 113; # Uses &division
Declaring our variable with state tells Perl to retain the variable’s value between calls
to the subroutine and to make the variable private to the subroutine:
use 5.010;
sub marine {
state $n = 0; # private, persistent variable $n
$n += 1;
print "Hello, sailor number $n!/n";
}
This is something you’ll want to do fairly often, so
naturally Perl has a shortcut for it. The shortcut looks like this:
while (<STDIN>) {
print "I saw $_";
}
The diamond operator is actually a special kind of line-input operator. But instead of
getting the input from the keyboard, it comes from the user’s choice of input:†
while (defined($line = <>)) {
chomp($line);
print "It was $line that I saw!/n";
}
we may use the same
shortcut we saw earlier to read the input into $_ by default:
while (<>) {
chomp;
print "It was $_ that I saw!/n";
}
there’s a difference between printing an array and interpo-
lating an array:
print @array;      # print a list of items
print "@array";    # print a string (containing an interpolated array)
Formatted Output with printf
printf "Hello, %s; your password expires in %d days!/n",
$user, $days_to_die;
To print a number in what’s generally a good way, use %g,* which automatically chooses
floating-point, integer, or even exponential notation as needed:
printf "%g %g %g/n", 5/2, 51/17, 51 ** 17; # 2.5 3 1.0683e+29
To print a real percent sign, use %%, which is special in that it uses no element from the
list:‡
printf "Monthly interest rate: %.2f%%/n",
5.25/12; # the value looks like "0.44%"
Arrays and printf
my @items = qw( wilma dino pebbles );
my $format = "The items are:/n" . ("%10s/n" x @items);
## print "the format is >>$format<</n"; # for debugging
printf $format, @items;
you can even combine these:
printf "The items are:/n".("%10s/n" x @items), @items;
there are also six special filehandle names that Perl already uses for its own pur-
poses: STDIN, STDOUT, STDERR, DATA, ARGV, and ARGVOUT.*
Opening a Filehandle
open CONFIG, "dino";
open CONFIG, "<dino";
open BEDROCK, ">fred";
open LOG, ">>logfile";
In modern versions of Perl (starting with Perl 5.6), you can use a “three-argument” open:
open CONFIG, "<", "dino";
open BEDROCK, ">", $file_name;
open LOG, ">>", &logfile_name();
Closing a Filehandle
close BEDROCK;
If the open fails, die will terminate the program and tell you that it cannot create the
logfile. But what’s that $! in the message? That’s the human-readable complaint from
the system. In general, when the system refuses to do something we’ve requested (like
opening a file), $! will give you a reason (perhaps “permission denied” or “file not
found,” in this case).
if ( ! open LOG, ">>logfile") {
die "Cannot create logfile: $!";
}
Using Filehandles
if ( ! open PASSWD, "/etc/passwd") {
die "How did you get logged in? ($!)";
}
while (<PASSWD>) {
chomp;
...
}
A filehandle open for writing or appending may be used with print or printf, appearing
immediately after the keyword but before the list of arguments:
print LOG "Captain's log, stardate 3.14159/n"; # output goes to LOG
printf STDERR "%d percent complete./n", $done/$total * 100;
Changing the Default Output Filehandle
select BEDROCK;
print "I hope Mr. Slate doesn't find out about this./n";
print "Wilma!/n";
if you wanted to be sure that the logfile gets its
entries at once, in case you might be reading the log to monitor progress of your long-
running program, you could use something like this:
select LOG;
$| = 1; # don't keep LOG entries sitting in the buffer
select STDOUT;
# ... time passes, babies learn to walk, tectonic plates shift, and then...
print LOG "This gets written to the LOG at once!/n";
 It’s the same as print, although it adds
a newline to the end. These forms all output the same thing:
use 5.010;
print "Hello!/n";
print "Hello!", "/n";
say "Hello!";
say BEDROCK "Hello!";
To access an element of a hash, use syntax that looks like this:
$hash{$some_key}
The Hash As a Whole
%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
"wilma", 1.72e30, "betty", "bye/n");
@any_array = %some_hash;
print "@any_array/n";
# might give something like this:
# betty bye (and a newline) wilma 1.72e+30 foo 35 2.5 hello bar 12.4
Hash Assignment
%new_hash = %old_hash;
It’s more common to transform the hash in some way, though. For example, we could
make an inverse hash:
%inverse_hash = reverse %any_hash;
in the Perl grammar,
any time that you need a comma ( , ), you can use the big arrow instead; it’s all the
same to Perl.† So here’s another way to set up the hash of last names:
my %last_name = ( # a hash may be a lexical variable
"fred"=>"flintstone",
"dino"=>undef,
"barney" =>"rubble",
"betty" =>"rubble",
);
keys function and values function
my %hash = ("a" => 1, "b" => 2, "c" => 3);
my @k = keys %hash;
my @v = values %hash;
The each Function
while ( ($key, $value) = each %hash ) {
print "$key => $value/n";
}
simply sort the keys, perhaps something like this:
foreach $key (sort keys %hash) {
$value = $hash{$key};
print "$key => $value/n";
# Or, we could have avoided the extra $value variable:
# print "$key => $hash{$key}/n";
}
The exists Function
if (exists $books{"dino"}) {
print "Hey, there's a library card for dino!/n";
}
The delete Function
my $person = "betty";
delete $books{$person}; # Revoke the library card for $person
Hash Element Interpolation
foreach $person (sort keys %books) {
if ($books{$person}) {
print "$person has $books{$person} items/n";
}
}
The %ENV hash
Using Simple Patterns
$_ = "yabba dabba doo";
if (/abba/) {
print "It matched!/n";
}
se the /1 back
reference to denote that we want to match the same four characters after the d:
$_ = "yabba dabba doo";
if (/y(....) d/1/) {
print "It matched the same after y and d!/n";
}
Now, this brings up the question “How do I know which group gets which number?”
Fortunately, Larry did the easiest thing for humans to understand: just count the order
of the opening parenthesis and ignore nesting:
$_ = "yabba dabba doo";
if (/y((.)(.)/3/2) d/1/) {
print "It matched!/n";
}
You might be able to see this if you write out the regular expression to see the different
parts (although this isn’t a valid regular expression*):
(     # first open parenthesis
(.)   # second open parenthesis
(.)   # third open parenthesis
/3
/2
)
By using /g{1}, we disambiguate the back reference and the literal parts of the pattern:*
use 5.010;
$_ = "aa11bb";
if (/(.)/g{1}11/) {
print "It matched!/n";
}
Perl 5.10 adds more character classes for whitespace. The /h shortcut only matches
horizontal whitespace, which you can write as the character class [/t ] to match a tab
and a space. The /v shortcut only matches vertical whitespace, or [/f/n/r]. The /R
shortcut matches any sort of linebreak, meaning that you don’t have to think about
which operating system you’re using and what it thinks a linebreak is since /R will figure
it out.
Another compound character class is [/d/D], which means any digit, or any nondigit.
That is to say, any character at all! This is a common way to match any character, even
a newline. (As opposed to ., which matches any character except a newline.) 
Case-Insensitive Matching with /i
print "Would you like to play a game? ";
chomp($_ = <STDIN>);
if (/yes/i) { # case-insensitive match
print "In that case, I recommend that you go bowling./n";
}
Matching Any Character with /s
$_ = "I saw Barney/ndown at the bowling alley/nwith Fred/nlast night./n";
if (/Barney.*Fred/s) {
print "That string mentions Fred after Barney!/n";
}
/x allows you to add arbitrary whitespace to a pattern to
make it easier to read:
/-?/d+/.?/d*/        # what is this doing? 
/ -? /d+ /.? /d* /x  # a little better
Remember that in Perl, comments may be included as part of the whitespace. Now we
can put comments into that pattern to tell what it’s really doing:
/
-?    #an optional minus sign
/d+   #one or more digits before the decimal point
/.?   #an optional decimal point
/d*   #some optional digits after the decimal point
/x    #end of string
Anchors aren’t just at the ends of the string. The word-boundary anchor, /b, matches
at either end of a word.‡ So you can use //bfred/b/ to match the word fred but not
frederick or alfred or manfred mann. This is similar to the feature often called something
like “match whole words only” in a word processor’s search command.
The nonword-boundary anchor is /B; it matches at any point where /b would not
match. So the pattern //bsearch/B/ will match searches, searching, and searched, but
not search or researching.
The Binding Operator, =~
my $some_other = "I dream of betty rubble.";
if ($some_other =~ //brub/) {
print "Aye, there's the rub./n";
}
you could use more than one memory at once:
$_ = "Hello there, neighbor";
if (/(/S+) (/S+), (/S+)/) {
print "words were $1 $2 $3/n";
}
We add a question mark and a colon after the
opening parenthesis, (?:),* and that tells Perl we use these parentheses only for
grouping.
if (/(?:bronto)?saurus (steak|burger)/) {
print "Fred wants a $1/n";
}
 Perl 5.10 lets us name the captures directly
in the regular expression. It saves the text it matches in the hash named %+
: the key is
the label we used and the value is the part of the string that it matched. To label a match
variable, we use (?<LABEL>PATTERN) where we replace LABEL with our own names.* We
label the first capture name1 and the second one name2, and look in $+{name1} and
$+{name2} to find their values:
use 5.010;
my $names = 'Fred or Barney';
if( $names =~ m/(?<name1>/w+) (?:and|or) (?<name2>/w+)/ ) {
say "I saw $+{name1} and $+{name2}";
}
The part of the
string that actually matched the pattern is automatically stored in $&:
if ("Hello there, neighbor" =~ //s(/w+),/) {
print "That actually matched '$&'./n";
}
Whatever came before the matched section is in $`, and whatever was after it is in $'.
if ("Hello there, neighbor" =~ //s(/w+),/) {
print "That was ($`)($&)($')./n";
}
Table 8-1. Regular expression precedence
Regular expression feature Example
Parentheses (grouping or memory) (...), (?:...), (?<LABEL>...)
Quantifiers a* a+ a? a{n,m}
Anchors and sequence abc ^a a$
Alternation a|b|c
Atoms a [abc] /d /1
This program is useful to test out a pattern on some strings and see just what it matches,
and where:
#!/usr/bin/perl
while (<>) {    # take one input line at a time
chomp;
if (/YOUR_PATTERN_GOES_HERE/) {
print "Matched: |$`<$&>$'|/n";   # the special match vars
} else {
print "No match: |$_|/n";
}
}
Substitutions with s///
$_ = "He's out bowling with Barney tonight.";
s/Barney/Fred/; # Replace Barney with Fred
print "$_/n";
The /g modifier tells
s/// to make all possible nonoverlapping* replacements:
$_ = "home, sweet home!";
s/home/cave/g;
print "$_/n"; # "cave, sweet cave!"
Different Delimiters
s#^https://#http://#;
s{fred}{barney};
s[fred](barney);
The Binding Operator
$file_name =~ s#^.*/##s; # In $file_name, remove any Unix-style path
The /U escape forces what follows to all uppercase:
$_ = "I saw Barney with Fred.";
s/(fred|barney)//U$1/gi; # $_ is now "I saw BARNEY with FRED."
Similarly, the /L escape forces lowercase. Continuing from the previous code:
s/(fred|barney)//L$1/gi;  # $_ is now "I saw barney with fred."
By default, these affect the rest of the (replacement) string, or you can turn off case
shifting with /E:
s/(/w+) with (/w+)//U$2/E with $1/i; # $_ is now "I saw FRED with barney."
When written in lowercase (/l and /u ), they affect only the next character:
s/(fred|barney)//u$1/ig;  # $_ is now "I saw FRED with Barney."
The split Operator
@fields = split /separator/, $string;
Here’s a typical split pattern, splitting on colons:
@fields = split /:/, "abc:def:g:h";  # gives ("abc", "def", "g", "h")
The join Function
my $result = join $glue, @pieces;
The /g modifier that you first saw on s/// also works with m//, which lets it match at
more than one place in a string. In this case, a pattern with a pair of parentheses will
return a memory from each time it matches:
my $text = "Fred dropped a 5 ton granite block on Mr. Slate";
my @words = ($text =~ /([a-z]+)/ig);
print "Result: @words/n";
# Result: Fred dropped a ton granite block on Mr Slate
Nongreedy Quantifiers
I thought you said Fred and <BOLD>Velma</BOLD>, not <BOLD>Wilma</BOLD>
we want a nongreedy quantifier.
The nongreedy form of star is *?, so the substitution now looks like this:
s#<BOLD>(.*?)</BOLD>#$1#g;
Matching Multiple-Line Text
$_ = "I'm much better/nthan Barney is/nat bowling,/nWilma./n";
print "Found 'wilma' at start of line/n" if /^wilma/b/im;
Updating Many Files
#!/usr/bin/perl -w
use strict;
chomp(my $date = `date`);
$^I = ".bak";
while (<>) {
s/^Author:.*/Author: Randal L. Schwartz/;
s/^Phone:.*/n//;
s/^Date:.*/Date: $date/;
print;
}
Let’s say it’s time for the diamond to open our file fred03.dat. It opens it like before,
but now it renames it, calling it fred03.dat.bak.* We’ve still got the same file open, but
now it has a different name on the disk. Next, the diamond creates a new file and gives
it the name fred03.dat. That’s okay; we weren’t using that name any more. And now
the diamond selects the new file as the default for output, so that anything that we print
will go into that file.† So now the while loop will read a line from the old file, update
that, and print it out to the new file. This program can update thousands of files in a
few seconds on a typical machine. Pretty powerful, huh?
In-Place Editing from the Command Line
$ perl -p -i.bak -w -e 's/Randall/Randal/g' fred*.dat
 it’s as if we had written a program like this, and put it to work on all of those fred*.dat files:
#!/usr/bin/perl -w
$^I = ".bak";
while (<>) {
s/Randall/Randal/g;
print;
}
Using unless says to run the block of code unless this condition is true. 
unless ($fred =~ /^[A-Z_]/w*$/i) {
  print "The value of /$fred doesn't look like a Perl identifier name./n";
}else{
  #Do nothing
}
you can rewrite it (either in your head or in reality) as an if test:
if ($fred =~ /^[A-Z_]/w*$/i) {
  # Do nothing
} else {
  print "The value of /$fred doesn't look like a Perl identifier name./n";
}
The until Control Structure
until ($j > $i) {
  $j *= 2;
}
the if modifier works in a way analogous to an if block:
print "$n is a negative number./n" if $n < 0;
if ($n < 0) {
  print "$n is a negative number./n";
}
 If
you’ve got the two semicolons, it’s a computed for loop (like we’ve just been talking
about). If you don’t have the semicolons, it’s really a foreach loop:
for (1..10) {  # Really a foreach loop from 1 to 10
  print "I can count to $_!/n";
}
The last Operator
# Print all input lines mentioning fred, until the __END__ marker
while (<STDIN>) {
  if (/__END__/) {
    # No more input on or after this marker line
    last;
  } elsif (/fred/) {
    print;
  }
}
## last comes here #
The next Operator
# Analyze words in the input file or files
while (<>) {
  foreach (split) {  # break $_ into words, assign each to $_ in turn
    $total++;
    next if //W/;    # strange words skip the remainder of the loop
    $valid++;
    $count{$_}++;    # count each separate word
    ## next comes here ##
  }
}
print "total things = $total, valid words = $valid/n";
foreach $word (sort keys %count) {
  print "$word was seen $count{$word} times./n";
}
The redo Operator
It says to go back to the top of the
current loop block, without testing any conditional expression or advancing to the next
iteration. 
# Typing test
my @words = qw{ fred barney pebbles dino wilma betty };
my $errors = 0;
foreach (@words) {
  ## redo comes here ##
  print "Type the word '$_': ";
  chomp(my $try = <STDIN>);
  if ($try ne $_) {
    print "Sorry - That's not right./n/n";
    $errors++;
    redo;  # jump back up to the top of the loop
  }
}
print "You've completed the test, with $errors errors./n";
Labeled Blocks
LINE: while (<>) {
  foreach (split) {
    last LINE if /__END__/;  # bail out of the LINE loop
    ...
  }
}
Here’s a trick you might see used to code up a nice multiway branch:
my $size =
  ($width < 10) ? "small"  :
  ($width < 20) ? "medium" :
  ($width < 50) ? "large"  :
                  "extra-large"; # default
The defined-or Operator
Perl 5.10 gets around this sort of bug with the defined-or operator, //, which short-
circuits when it finds a defined value, no matter if that value on the lefthand side is true
or false. Even if someone’s last name is 0, this version still works:
use 5.010;
my $last_name = $last_name{$someone} // '(No last name)';.
 if you expect that you
might try to print an undefined value, you can use the empty string instead:
use 5.010;
use warnings;
my $name;  # no value, so undefined!
printf "%s", $name // '';
Using Only Some Functions from a Module
Here,we’ll get nothing but basename:
use File::Basename qw/ basename /;"
we use the -e file test, testing a filename for
existence:
die "Oops! A file called '$filename' already exists./n"
if -e $filename;
File Test Operators
File tests and their meanings
-r File or directory is readable by this (effective) user or group
-w File or directory is writable by this (effective) user or group
-x File or directory is executable by this (effective) user or group
-o File or directory is owned by this (effective) user
-R File or directory is readable by this real user or group
-W File or directory is writable by this real user or group
-X File or directory is executable by this real user or group
-O File or directory is owned by this real user
-e File or directory name exists
-z File exists and has zero size (always false for directories)
-s File or directory exists and has nonzero size (the value is the size in bytes)
-f Entry is a plain file
-d Entry is a directory
-l Entry is a symbolic link
-S Entry is a socket
-p Entry is a named pipe (a “fifo”)
-b Entry is a block-special file (like a mountable disk)
-c Entry is a character-special file (like an I/O device)
-u File or directory is setuid
-g File or directory is setgid
-k File or directory has the sticky bit set
-t The filehandle is a TTY (as reported by the isatty() system function; filenames can’t be tested by this test)
-T File looks like a “text” file
-B File looks like a “binary” file
-M Modification age (measured in days)
-A Access age (measured in days)
-C Inode-modification age (measured in days)
The virtual filehandle _
(just the underscore) uses the information from the last file lookup that a file test op-
erator performed. Perl only has to look up the file information once now:
if( -r $file and -w _ ) {
... }
Perl 5.10 lets us “stack” our file test operators by
lining them all up before the filename:
use 5.010;
if( -w -r $file ) {
print "The file is both readable and writable!/n";
}
The stat and lstat Functions
my($dev, $ino, $mode, $nlink, $uid, $gid, $rdev,
$size, $atime, $mtime, $ctime, $blksize, $blocks)
= stat($filename);
The names here refer to the parts of the stat structure, described in detail in the
stat(2) manpage. You should probably look there for the detailed descriptions. But in
short, here’s a quick summary of the important ones:
$dev and $ino
The device number and inode number of the file. Together they make up a “license
plate” for the file. Even if it has more than one name (hard link), the combination
of device and inode numbers should always be unique.
$mode
The set of permission bits for the file, and some other bits. If you’ve ever used the
Unix command ls -l to get a detailed (long) file listing, you’ll see that each line of
output starts with something like -rwxr-xr-x. The nine letters and hyphens of file
permissions† correspond to the nine least-significant bits of $mode, which would,
in this case, give the octal number 0755. The other bits, beyond the lowest nine,
indicate other details about the file. So, if you need to work with the mode, you’ll
generally want to use the bitwise operators covered later in this chapter.
$nlink
The number of (hard) links to the file or directory. This is the number of true names
that the item has. This number is always 2 or more for directories and (usually) 1
for files. You’ll see more about this when we talk about creating links to files in
Chapter 13. In the listing from ls -l, this is the number just after the permission-
bits string.
$uid and $gid
The numeric user ID and group ID showing the file’s ownership
$size
The size in bytes, as returned by the -s file test.
$atime, $mtime, and $ctime
The three timestamps, but here they’re represented in the system’s timestamp for-
mat: a 32-bit number telling how many seconds have passed since the Epoch, an
arbitrary starting point for measuring system time. On Unix systems and some
others, the Epoch is the beginning of 1970 at midnight Universal Time, but the
Epoch is different on some machines. There’s more information later in this chapter
on turning that timestamp number into something useful.
 a string like Thu May 31 09:48:18 2007. Perl can do that with
the localtime function in a scalar context:
my $timestamp = 1180630098;
my $date = localtime $timestamp;
In a list context, localtime returns a list of numbers, several of which may not be quite
what you’d expect:
my($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst)
= localtime $timestamp;
There are two related functions that you’ll also find useful. The gmtime function is just
the same as localtime, except that it returns the time in Universal Time (what we once
called Greenwich Mean Time). If you need the current timestamp number from the
system clock, just use the time function. Both localtime and gmtime default to using
the current time value if you don’t supply a parameter:
my $now = gmtime; # Get the current universal timestamp as a string
Bitwise Operators
10 & 12 Bitwise-and—which bits are true in both operands (this gives 8)
10 | 12 Bitwise-or—which bits are true in one operand or the other (this gives 14)
10 ^ 12 Bitwise-xor—which bits are true in one operand or the other but not both (this gives 6)
6 << 2 Bitwise shift left—shift the left operand the number of bits shown by the right operand, adding zero-bits at the
        least-significant places (this gives 24)
25 >> 2 Bitwise shift right—shift the left operand the number of bits shown by the right operand, discarding the least-
         significant bits (this gives 6)
~ 10 Bitwise negation, also called unary bit complement—return the number with the opposite bit for each bit in
      the operand (this gives 0xFFFFFFF5, but see the text)
The chdir operator changes the working directory. It’s just like the Unix shell’s cd
command:
chdir "/etc" or die "cannot chdir to /etc: $!";
@all_files gets all the files in the current directory
my @all_files = glob "*";
my @pm_files = glob "*.pm";
using angle brackets means both filehandle reading and globbing,
my @all_files = <*>; ## exactly the same as my @all_files = glob "*";
Another way to get a list of names from a given directory is with a directory handle. A
directory handle looks and acts like a filehandle. You open it (with opendir instead of
open), you read from it (with readdir instead of readline), and you close it (with close
dir instead of close). But instead of reading the contents of a file, you’re reading the
names of files (and other things) in a directory. For example:
my $dir_to_process = "/etc";
opendir DH, $dir_to_process or die "Cannot open $dir_to_process: $!";
foreach $file (readdir DH) {
print "one file in $dir_to_process is $file/n";
}
closedir DH;
Removing Files
At the Unix shell level,we’d type an rm command to remove a file or files:
$ rm slate bedrock lava
In Perl, we use the unlink operator:
unlink "slate", "bedrock", "lava";
foreach my $file (qw(slate bedrock lava)) {
unlink $file or warn "failed on $file: $!/n";
}
Renaming Files
rename "old", "new";
rename "over_there/some/place/some_file", "some_file";
uses the Perl link function
to create a new link:
link "chicken", "egg"
or warn "can't link chicken to egg: $!";
creates a symbolic link
with Perl’s symlink function, like this:
symlink "dodgson", "carroll"
or warn "can't symlink dodgson to carroll: $!";
This is similar to what would happen if Barney used the command ln-s dodgson car-
roll from the shell.
To find out where a symbolic link is pointing, use the readlink function. This will tell
you where the symlink leads, or it will return undef if its argument wasn’t a symlink:
my $where = readlink "carroll"; 
my $perl = readlink "/usr/local/bin/perl"; 
Making a directory inside an existing directory is easy. Just invoke the mkdir function:
mkdir "fred", 0755 or warn "Cannot make fred directory: $!";
mkdir $name, oct($permissions);
To remove empty directories, use the rmdir function in a manner similar to the
unlink function, although it can only remove on directory per call:
foreach my $dir (qw(fred barney betty)) {
rmdir $dir or warn "cannot rmdir $dir: $!/n";
}
my $temp_dir = "/tmp/scratch_$$";
# based on process ID; see the text
mkdir $temp_dir, 0700 or die "cannot create $temp_dir: $!";
...
# use $temp_dir as location of all temporary files
...
unlink glob "$temp_dir/* $temp_dir/.*"; # delete contents of $temp_dir
rmdir $temp_dir;
# delete now-empty directory
The initial temporary directory name includes the current process ID, which is unique
for every running process and is accessed with the $$ variable (similar to the shell).
Modifying Permissions
chmod 0755, "fred", "barney";
Changing Ownership
my $user = 1004;
my $group = 100;
chown $user, $group, glob "*.o";
defined(my $user = getpwnam "merlyn") or die "bad user";
defined(my $group = getgrnam "users") or die "bad group";
chown $user, $group, glob "/home/merlyn/*";
Changing Timestamps
my $now = time;
my $ago = $now − 24 * 60 * 60;# seconds per day
utime $now, $ago, glob "*";# set access to now, mod to a day ago
Finding a Substring with index
$where = index($big, $small);
my $last_slash = rindex("/etc/passwd", "/");  # value is 4  with rindex
Now here’s something really cool: The selected portion of the string can be changed if
the string is a variable
my $string = "Hello, world!";
substr($string, 0, 5) = "Goodbye";  # $string is now "Goodbye, world!"
 the fourth argument is the replacement substring:
my $previous_value = substr($string, 0, 5, "Goodbye");
Formatting Data with sprintf
my $date_tag = sprintf
  "%4d/%02d/%02d %2d:%02d:%02d",
  $yr, $mo, $da, $h, $m, $s;
You could now write a numeric sort subroutine like this:
sub by_number {
  # a sort subroutine, expect $a and $b
  if ($a < $b) { −1 } elsif ($a > $b) { 1 } else { 0 }
}
To use the sort subroutine, just put its name (without an ampersand) between the
keyword sort and the list you’re sorting. This example puts a numerically sorted list
of numbers into @result:
my @result = sort by_number @some_numbers;
we use the spaceship operator (<=>).* This operator compares two numbers and returns
−1,  0, or  1 as needed to sort them numerically. So we could have written that sort
subroutine better, like this:
sub by_number { $a <=> $b } # <=>    cmp : ASCIIbetically
my @numbers = sort { $a <=> $b } @some_numbers;
 this is another
way to get a reversed numeric sort:
my @descending = reverse sort { $a <=> $b } @some_numbers;
my @descending = sort { $b <=> $a } @some_numbers;
The Smart Match Operator
my $flag = 0;
foreach my $key ( keys %names ) {
    next unless $key =~ /Fred/;
    $flag = $key;
    last;
    }
print "I found a key matching 'Fred'. It was $flag/n" if $flag;
#use smart match
use 5.010;
say "I found a key matching 'Fred'" if %names ~~ /Fred/;
use 5.010;
say "The arrays have the same elements!"
    if @names1 ~~ @names2;
 Smart match operations for pairs of operands
Example Type of match
%a ~~ %b Hash keys identical
%a ~~ @b At least one key in %a is in @b
%a ~~ /Fred/ At least one key matches pattern
%a ~~ 'Fred' Hash key existence exists $a{Fred}
   
@a ~~ @b Arrays are the same
@a ~~ /Fred/ At least one element matches pattern
@a ~~ 123 At least one element is 123, numerically
@a ~~ 'Fred' At least one element is 'Fred', stringwise
   
$name ~~ undef $name is not defined
$name ~~ /Fred/ Pattern match
123 ~~ '123.0' Numeric equality with “numish” string
'Fred' ~~ 'Fred' String equality
123 ~~ 456 Numeric equality

The given Statement
use 5.010;
given( $ARGV[0] ){
when( /fred/i) { say 'Name has fred in it' }
when( /^Fred/) { say 'Name starts with Fred' }
when( 'Fred') { say 'Name is Fred' }
default{ say "I don't see a Fred" }
}

To go through many elements, you don’t need the given. Let foreach put the current
element in $_ on its own. If you want to use smart matching, the current element has
to be in $_.
use 5.010;
foreach ( @names ) { # don't use a named variable!
when( /fred/i ) { say 'Name has fred in it'; continue }
when( /^Fred/ ) { say 'Name starts with Fred'; continue }
when( 'Fred' ) { say 'Name is Fred'; }
default
{ say "I don't see a Fred" }
}

system 'ls -l $HOME';

Everything we’ve just said about system syntax and semantics is also true about the
exec function, except for one (very important) thing. The system function creates a child
process, which then scurries off to perform the requested action while Perl naps. The
exec function causes the Perl process itself to perform the requested action. Think of it
as more like a “goto” than a subroutine call.
ro

Using Backquotes to Capture Output
my $now = `date`;# grab the output of date
print "The time is now $now"; # newline already present

Note that this will make the standard error output intermingled with the standard
output, much as it appears on the terminal
my $output_with_errors = `frobnitz -enable 2>&1`;

stay away from commands that read standard input. If you’re not sure whether
something reads from standard input, then add a redirection from /dev/null for input,
like this:
my $result = `some_questionable_command arg arg argh </dev/null`;

Processes as Filehandles
open DATE, "date|" or die "cannot pipe from date: $!";
open MAIL, "|mail merlyn" or die "cannot pipe to mail: $!";
get data from a filehandle opened for reading, we’ll just do
the normal read:
my $now = <DATE>;
And to send data to the mail process (waiting for the body of a message to deliver to
merlyn on standard input), a simple print-with-a-filehandle will do:
print MAIL "The time is now $now"; # presume $now ends in newline
finish sending the email, close the handle:
close MAIL;
die "mail: non-zero exit of $?" if $?;

send a SIGINT to process 4201
kill 2, 4201 or die "Cannot signal 4201 with SIGINT: $!";

Trapping Errors with eval
eval { $barney = $fred / $dino } ;
print "An error occurred: $@" if $@;

Picking Items from a List with grep
my @odd_numbers = grep { $_ % 2 } 1..1000;
That line gets a list of 500 odd numbers in one quick line of code.

Transforming Items from a List with map
my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95);
my @formatted_data = map { &big_money($_) } @data;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值