《Beginning Perl》读书笔记3:6~10章

  • 声明:subfunction_name;
  • 定义:subfunction_name {...}
  • 函数调用同C:
    • example_subroutine();或example_subroutine;
    • example_subroutine('Perl is', 'my favorite', $language);或example_subroutine 'Perl is', 'my favorite', $language;
    • 调用时需保证之前已有声明/定义
  • 返回值:函数的最后一行代码可以写表达式作为返回值,例如写$total;也可以使用return语句在函数体中的任意位置返回返回值
  • 函数内部通过@_变量访问传入参数:
  • Perl中按引用传参,改变输入参数将影响函数外的变量
  • 实现默认参数值的小技巧:
sub log_warning {

my $message = shift || "Something's wrong";

my $time = shift || localtime; # Default to now.

print "[$time] $message\n";

}

  • 实现参数命名的小技巧:
    • 调用:logon(username => $name, password => $pass, host => $hostname);
    • 定义:
sub logon {

die "Parameters to logon should be even" if @_ % 2;

my %args = @_;

print "Logging on to host $args{hostname}\n";

...

}

第7章:正则表达式

  • 正则表达式以双斜线对//包裹,//中可以使用变量,变量将被代换为对应的值
  • 正则式匹配:str =~ /re/若str匹配/re/成功为true,反之false;!~则与=~相反
  • /re/等价于$_ =~ /re/
  • 进行匹配后,可以使用$1,$2,$3...获得字符串中匹配成功的子串
    • 因为不知道有多少个匹配成功的子串,所以需要用defined算符一一检验$1, $2, $3是否已定义,stupid
  • //正则式中以下元字符(metacharacter)需要使用\转义:. * ? + [ ( ) { ^ $ | \ /
  • \Q可用于关闭元字符,\E用于结束\Q。\Q...\E之间的部分可自由使用上一要点中提到的元字符
  • 锚点^表示从字符串起始处匹配,而$则表示匹配至字符串末尾结束
  • []可定义字符集,例如[abc]匹配a,b或c,[0-9]匹配0,1,2,3,4,5,6,7,8,9任一。[]中使用^表达反义,即[^eo]可匹配除e,o外任意字符
  • 几个等价:\d等价于[0-9],\w等价于[0-9A-Za-z_],\s等价于[ \t\n\r\f],\D等价于[^0-9],\W等价于[^0-9A-Za-z_],\S等价于[^ \t\n\r\f],.等价于任意字符(换行符除外)
  • |可用于表示或,例如yes|maybe可匹配yes或maybe,ye(s|t)匹配yes或yet
  • ?意味?前面的记号出现0或1次,例如(word )?is可匹配word is和is
  • +则为1次及1次以上,*为任意次(包含0次)
    • /bea?t/匹配beat和bet
    • /bea+t/匹配beat, beaat, beaaat...
    • /bea*t/匹配bet, beat, beaat, beaaat...
  • {}则可以定义具体的出现次数,例如\s{2,3}可匹配2个空格,也可匹配3个空格。{x}代表x次,{x,}则代表x次及x次以上
  • 正则式匹配器的工作原则:
    • 一旦匹配无法继续(下一个字符无法满足正则式定义),立即停止匹配
    • 一旦匹配成功,马上结束匹配
    • 遇+*?三个字符时取最长匹配,即匹配至无法匹配时再匹配之后的正则式与字符串
    • 最近分支原则:若存在分支匹配(例如[a-z]或ye(s|t)这种情况)则从前向后依次尝试,若尝试失败则取下一个,直到成功匹配或所有情况匹配失败
  • 使用正则式进行替换:str =~ s/find/replace/;可用于将str中满足find模式的首个子串替换为replace,若不指定str,执行s/find/replace/;为对$_操作,在末尾加g修饰符可替换所有子串
$_ = "Awake! Awake! Fear, Fire, Foes! Awake! Fire, Foes! Awake!";

s/Foes/Flee/;

print $_,"\n";

输出:

Awake! Awake! Fear, Fire, Flee! Awake! Fire, Foes! Awake!

$_ = "there are two major products that come out of Berkeley: LSD and UNIX";

s/(\w+)\s+(\w+)/$2 $1/g;

print $_, "?\n";

输出:

are there major two that products out come Berkeley of: and LSD UNIX?

  • 类似q//和qq//,//和s///也可以使用别的分隔符,当在匹配(//)中使用其他分隔符时,需要使用m作为前缀,例如m/^\s*[A-Z]/;m#^\s*[A-Z]#;m{^\s*[A-Z]};等,而s/old text/new text/g;则可以写为s{old text}{new text}g;也可以出于清晰写为:

s{old text}

{new text}g;

再如s/\/usr\/local\/share\//\/usr\/share\//g;可写为s#/usr/local/share/#/usr/share/#g;

  • 修饰符
    • /m将字符串作为多行字符串处理,在这种情况下^$不再分别匹配单词首尾,而是匹配行首行尾
    • /s将字符串作为单行字符串处理,此时.匹配包括换行符在内的所有字符
    • /g:匹配时若有多个可匹配子串则全部匹配;替换时则替换所有可匹配子串,使用此修饰符时可使用\G锚点匹配最后一个可匹配子串的最后一个字符位置
    • /x允许以多行方式书写正则式,且可以添加注释
  • split(re, str)将str按照re分为多个子串,返回包含这些子串的列表。不指定str则默认对$_操作。例如split /:/, “kake:x:10018:10020::/home/kake:/bin/bash”可得(“kake”, “x”, “10018”, “10020”, “”, “/home/kake”, “/bin/bash”)
  • join(str, list)可用str将list中各个元素连接为一个字符串,并返回这个字符串,例如join “#”, (“kake”, “x”, “10018”, “10020”, “”, “/home/kake”, “/bin/bash”)可得“kake:x:10018:10020::/home/kake:/bin/bash”

第8章:文件与数据

  • 打开文件:open(filehandle, mode, filename)例如open(FH, '<', 'input.txt')
    • 打开成功时返回true,反之false
    • 也可以写作open(FH, '< input.txt')
  • 访问模式:>写 <读 >>追加
  • close(filehandle)用于关闭文件句柄,例如close(FH);
  • 标量读入:my $line = <FH>,读入一行
  • 列表读入:my @list = <FH>,读入所有行,每行为一个列表元素
  • 特殊文件句柄:<>(称为“钻石运算符”)
    • 当未在命令行参数中指定输入文件时,为<STDIN>
    • 否则为指定的文件句柄。可指定多个文件,按指定顺序逐个打开、逐行读取
  • @ARGV为存储命令行参数的字符串数组,例如以perl argv1.pl king crimson rocks运行时@ARGV为(‘king’, ‘crimson’, ‘rocks’)
  • <>本质上就是用@ARGV实现的。$ARGV为<>当前文件句柄指向文件的文件名
  • print FH list可以向FH指向的文件中输出list
  • $|变量设置是否使用OS的输出缓冲区,默认为0(使用),设为1后不使用
  • 管道:将上一个程序的STDOUT输出接入:open(FH, '-|', command);例如open(FH, '-|', 'perl sort2.pl gettysburg.txt');
  • 管道:将当前程序的STDOUT输出接入下个程序的STDIN:open(SORT, '|-', command);例如open(SORT, '|-', 'perl sort2.pl');
  • 管道:可使用IPC::Open2建立双向管道(未详述)
  • lc(str)将字符串str中字母转换为小写后输出,uc(str)则转换为大写
  • 类似shell的文件测试:(-operator $file),operator包括:
    • e $file存在时为true
    • f $file为文件(不是目录)时为true
    • d $file为目录时为true
    • z $file大小为0时为true
    • s $file大小不为0时为true
    • r $file可读时为true
    • w $file可写时为true
    • x $file可执行时为true
    • o $file为当前用户拥有时为true

第9章:字符串处理

  • length(str)返回str的长度
  • index(str, substr)返回str中substr第一次出现时的下标,substr不存在时返回-1
    • index(str, substr, mindex)指定从mindex开始查找
  • rindex(str, substr)返回str中substr最后一次出现时的下标,不存在时返回-1
    • rindex(str, substr, mindex)指定从mindex开始查找
  • substr(string, starting_index, length)返回string中从starting_index开始取length长度的子串
  • tr///用于字符替换,例如tr/old/new/将会建立如下字符替换规则:o->n, l->e, d->w,例如$string = ‘2011064’,而执行$string =~ tr/0123456789/abcdefghij/;或$string =~ tr/0-9/a-j/;后,$string变为‘cabbage’
    • d修饰符用于删除字符,例如my $vowels = $string =~ tr/aeiou//;并不能删除$string中的元音字母,而my $vowels = $string =~ tr/aeiou//d;就可以。再例如$string =~ tr/ //d;可删除$string中的所有空格

第10章:OS交互

  • %ENV保存了所有环境变量(改变%ENV并不能真正改变系统环境变量设置),例如$ENV{HOME},$ENV{PATH},$ENV{USER}等
  • 文件通配符:glob(pattern)函数用以返回下一个满足pattern的文件名,例如glob(‘*.pl’),等价于<*.pl>,表示所有扩展名为pl的文件。
while (glob('*.dat')) {

print "found a data file: $_\n";

}

  • 可以使用opendir打开一个目录,通过readdir函数读取其中包含的文件,closedir关闭:
opendir DH, "." or die "Couldn't open the current directory: $!";

while ($_ = readdir(DH)) { … }

closedir DH;

  • 以下函数与UNIX API相同或类似,可参照APUE(《UNIX环境高级编程》)
      • chdir(directory)
      • unlink(list_of_files) 可unlink多个文件
      • rename(old_file_name, new_file_name)
      • link(file_to_link_to, link_name)
      • symlink(file_to_link_to, sym_link_name)
      • readlink(sym_link_name)
      • mkdir(directory_name, mode)
      • rmdir(directory_name)
      • chmod(file_or_directory_name, mode)
      • system(command)
  • system()函数将执行命令的输出打印至控制台(STDOUT),返回进程的执行结果(个人推断:main函数的返回值)。而使用`command`则可将输出捕获,例如:
    • $output = `$command`;将$command执行的输出保存至字符串$output,包括换行符
    • @output = `$command`;将$command执行的输出保存至列表@output,每行一个元素,包括换行符