Sharing

2013年5月2日 星期四

Perl 學習手冊第六版筆記(四)

Chapter 10 More Control Structures


Loop Controls

The redo Operator


# 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
        ...
    }
}

The defined-or Operator


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.

my $last_name = $last_name{$someone} // '(No last name)';


Chapter 11 Perl Modules

Using Simple Modules

Using Only Some Functions from a Module


use File::Basename qw/ basename /;
use File::Basename ();

Chapter 12 File Tests

File Test Operators

File Test Meaning
-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)



Perl has a special shortcut to help you not do so much work. The virtual filehandle _ (just the underscore) uses the information from the last file lookup that a file test operator performed. Perl only has to look up the file information once now.

if (-r $file and -w _) {
    ... 
}

if (-r $file) {
    print "The file is readable!\n";
}

if (-w _) {
    print "The file is writable!\n";
}

# stack the file test

use 5.010;

if (-w -r $file) {
    print "The file is both readable and writable!\n";
}


The Stat and lstat Functions


If you need the (mostly useless) information about the symbolic link itself, use lstat rather than stat (which returns the same information in the same order). If the operand isn’t a symbolic link, lstat returns the same things that stat would.

my($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($filename);

Chapter 13 Directory Operations

Globbing



my @all_files = glob '*';
my @pm_files = glob '*.pm';
my @all_files_including_dot = glob '.* *';
my @all_files = <*>;           # exactly the same as my @all_files = glob "*";

my @files = ;          # a glob
my @lines = ;            # a filehandle read
my @lines = <$fred>;           # a filehandle read
my $name = 'FRED'; 
my @files = <$name/*>;         # a glob

my $name = 'FRED';
my @lines = <$name>; # an indirect filehandle read of FRED handle
my @lines = readline FRED; # read from FRED
my @lines = readline $name; # read from FRED

Files Operation


unlink 'slate', 'bedrock', 'lava';
unlink qw(slate bedrock lava);
unlink glob '*.o';
rename 'old', 'new';
link 'chicken', 'egg';
mkdir 'fred', 0755;
rmdir $temp_dir;
chmod 0755, 'fred', 'barney';
chown $user, $group, glob '*.o';


如果用 $file = "~/test.pl" 則會失敗, 需要用到 shell expansion 時, 必須要改用 <> 包起來
$file = <~/test.pl>                                # Name the file
open(INFO, $file) || die "Can't open file $file : $!\n"; # Open the file, print the error message if fail
close(INFO);                   # Close the file



Perl 學習手冊第六版筆記(三)


Chapter 7 In the World of Regular Expressions


http://perldoc.perl.org/perlre.html

Using Simple Patterns


Unicode Properties


http://perldoc.perl.org/perluniprops.html


if (/\p{Space}/) { # 26 different possible characters
    print "The string has some whitespace.\n";
}

if (/\p{Digit}/) { # 411 different possible characters
    print "The string has a digit.\n";
}

if (/\P{Space}/) { # Not space (many many characters!)
    print "The string has one or more non-whitespace characters.\n";
}


Back Reference

You denote a back reference as a backslash followed by a number, like \1, \2, and so on.
Refers to the capture of an already completed pattern match, like $1, $2, and so on,

$_ = "abba";
if (/(.)\1/) { # matches 'bb'
    print "It matched same character next to itself!\n";
}

$_ = "Hello there, neighbor";
if (/(\S+) (\S+), (\S+)/) {
print "words were $1 $2 $3\n";
}



Perl 5.10 introduced a new way to denote back references. Instead of using the back-slash and a number, you can use \g{N}, where N is the number of the back reference that you want to use.
$_ = "aa11bb";
if (/(.)\g{1}11/) {
    print "It matched!\n";
}

you can specify a relative back reference. You can rewrite the last example to use –1 as the number to do the same thing:

$_ = "aa11bb";
if (/(.)\g{–1}11/) {
    print "It matched!\n";
}

Chapter 8 Matching with Regular Expressions


Match Modifiers

Case-Insensitive Matching with /i


Matching Any Character with /s

If you might have newlines in your strings, and you want the dot to be able to match them, the /s modifier will do the job.

Adding Whitespace with /x

allows you to add arbitrary whitespace to a pattern, in order to make it easier to read

/-?[0-9]+\.?[0-9]*/               # what is this doing?
/ -? [0-9]+ \.? [0-9]* /x         # a little better

The Match Variables

Noncapturing Parentheses

To skip a match variable, you use (?:PATTERN)
if (/(?:bronto)?saurus (steak|burger)/) {
    print "Fred wants a $1\n";
}

Named Captures

To label a match variable, you use (?
my $names = 'Fred or Barney';
  if ( $names =~ m/(?<name1>\w+) (?:and|or) (?<name2>\w+)/ ) {
  say "I saw $+{name1} and $+{name2}";
}

my $names = 'Fred Flintstone and Wilma Flintstone';
  if ( $names =~ m/(?<last_name>\w+) and \w+ \g{last_name}/ ) {
  say "I saw $+{last_name}";
}

The Automatic Match Variables

$& : entire matched section
$` : holds whatever the regular expression engine had to skip over before it found the match
$' : has the remainder of the string that the pattern never got to

if ("Hello there, neighbor" =~ /\s(\w+),/) {
    print "That was ($`)($&)($').\n";       # show (Hello)( there,)( neighbor)
}

Instead of $`, $&, or $', you use ${^PREMATCH}, ${^MATCH}, or ${^POSTMATCH}


General Quantifiers

A comma-separated pair of numbers inside curly braces ({}) to specify exactly how few and how many repetitions you want.
So the pattern /a{5,15}/ will match from five to fifteen repetitions of the letter a
So, /(fred){3,}/ will match if there are three or more instances of fred


Precedence

Regular expression feature
Example
Parentheses (grouping or capturing)
(...), (?:...), (?
Quantifiers
a*, a+, a?, a{n,m}
Anchors and sequence
abc, ^, $, \A, \b, \z, \Z
Alternation
a|b|c
Atoms
a, [abc], \d, \1, \g{2}


Chapter 9 Processing Text with Regular Expressions


Substitutions with s///

Global Replacements with /g

Different Delimiters


These are acceptable.
s#^https://#http://#;
s{fred}{barney};
s[fred](barney);
s<fred>#barney#;

Case Shifting


\U: forces what follows to all uppercase
\L: forces what follows to all uppercase
\u: uppercase next character
\l: lowercase next character
\u\L: all lowercase but captialize the first letter
\l\U: all Uppercase but lower the first letter
\E: turn off case shifting

The split Operator

The join Function

m// in List Context

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>";
s#<BOLD>(.*?)</BOLD>#$1#g;


2013年5月1日 星期三

Perl 學習手冊第六版筆記(二)

Chapter 4 Subroutines

@_    =>  Parameter array, use $_[0], $_[1].... $[n] to access it.

Persistent, Private Variables


Sample of persistent scalar

use 5.010;
sub marine {
    state $n = 0; # private, persistent variable $n
    $n += 1;
    print "Hello, sailor number $n!\n";
}

Sample of persistent array/list

use v5.10;

running_sum( 5, 6 );
running_sum( 1..3 );
running_sum( 4 );

sub running_sum {
    state $sum = 0;
    state @numbers;
    foreach my $number ( @_ ) {
        push @numbers, $number;
        $sum += $number;
    }
    say "The sum of (@numbers) is $sum";
}

There’s a slight restriction on arrays and hashes as state variables, though. You can’t initialize them in list contexts

state @array = qw(a b c); # Error!

Chapter 5 Input and Output


Input from Standard Input

兩種寫法都可以, 第二種是第一種的 Shortcut
while (defined($_ = )) {
    print "I saw $_";
}

while () {
    print "I saw $_";
}

# not recommended, it will read all of the input before the loop can start running
foreach () {
    print "I saw $_";
}


Input from the Diamond Operator


Diamond Operator read invocation arguments as input files and merge them together.
If you give no invocation arguments, the program should process the standard input stream.

第二種是第一種的縮寫
while (defined($line = <>)) {
    chomp($line);
    print "It was $line that I saw!\n";
}

while (<>) {
    chomp;
    print "It was $_ that I saw!\n";
}



Special filehandle


STDIN, STDOUT, STDERR, DATA, ARGV, and ARGVOUT


open BEDROCK, '>:encoding(UTF-8)', $file_name;
open BEDROCK, '>:utf8', $file_name;
open BEDROCK, '>:encoding(iso-8859-1)', $file_name;
open BEDROCK, '>:crlf', $file_name;
binmode STDOUT; # don't translate line endings
binmode STDOUT, ':encoding(UTF-8)';


Fatal Errors with die


if ( ! open LOG, '>>', 'logfile' ) {
    die "Cannot create logfile: $!";
}

Using Filehandles


You can use a filehandle open for writing or appending with print or printf.
There is no comma between the filehandle and the items to be printed.

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

Default output may be changed with the select operator
select BEDROCK;
print "I hope Mr. Slate doesn't find out about this.\n";
print "Wilma!\n";

Setting the special $| variable to 1 will set the currently selected file handle to always flush the buffer after each output operation.
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";

Chapter 6 Hashes

The keys and values are both arbitrary scalars, but the keys are always converted to strings.

Hash Assignment


Now the keys are where the values used to be, and the values are where the keys used to be
my %inverse_hash = reverse %any_hash;

The keys and values Functions

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";
}

The exists Function


if (exists $books{"dino"}) {
    print "Hey, there's a library card for dino!\n";
}