### 缺点
### 整型
### 列表
给数组赋值,使用Ctrl+Z+回车完成输入"$var[0]"
为数组@var的第一个元素。"$var\[0]"
将字符"["转义,等价于"$var"."[0]"
, $var 被变量替换,[0]保持不变。"${var}[0]"
亦等价于"$var"."[0]"
。"$\{var}"
则取消了大括号的变量替换功能,包含文字:${var}.open(outfile,">outfile")
open(appendfile,">>appendfile")
close(myfile);
关闭文件。$line=
从文件中读取一行数据存储到简单变量$line中并把文件指针向后移动一行。
为标准输入文件,通常为键盘输入,不需要打开。@array=
把文件的全部内容读入数组@array,文件的每一行(含回车符)为@array的一个元素。open(outfile, ">outfile") #打开对应的文件
print outfile ("具体内容!")
-op expr
@ARGV
,可以用来分别处理各个命令行参数$ARGV[0]
是第一个参数# An example
$count = @ARGV;
print "The length of the command arguments is: $count.\n";
print "The arguments are: \n";
for($i=0;$i<$count;$i++){
print @ARGV[$i]." ";
}
print "\n";
<>
操作符实际上是对数组@ARGV
的隐含的引用,其工作原理为:
<>
时,打开以$ARGV[0]
为文件名的文件shift(@ARGV);
即把数组@ARGV
的元素向前移动一个,其元素数量即减少了一个<>
操作符读取在第一步打开的文件中的所有行/def/
即模式def
。split
将字符串用某种模式分成多个单词:@array=split(//,$line);
=~
检验匹配是否成功:$result=$var=~/abc/;
若在该字符串找到了该模式,则返回非零值,即true
,不匹配则返回0,即false
。!=~
则相反。字符+
+
意味着一个或多个相同的字符。
它尽量匹配尽可能多的相同字符。
当一行中各单词间的空格多于一个时,可以如下分割:
@array=split(/+/,$line);
split
函数每次遇到分割模式,总是开始一个新单词,因此若$line
以空格打头,则@array
的第一个元素即为空元素。
但其可以区分是否真有单词,如若$line
中只有空格,则@array
则为空数组。
且上例中TAB
字符被当作一个单词。
字符[]
和[^]
[]
意味着匹配一组字符中的一个^
表示除其之外的所有字符。字符*
和?
+
类似,区别在于*
匹配0个,1个或多个相同字符,?
匹配0个或1个该字符。\
。/\\/
/[0-9]/ # 任意数字
/[a-z]/ # 任意小写字母
/[A-Z]/ # 任意大写字母
/[0-9a-zA-Z] # 任意数字,大小写字母
锚 | 描述 |
---|---|
^ 或者\A |
仅匹配串首 |
$ 或者\Z |
仅匹配串尾 |
\b |
匹配单词边界 |
\B |
单词内部匹配 |
\
).
匹配除换行符外的所有字符,通常与*
合用{}
指定所匹配字符的 出现次数|
指定两个或多个选择来匹配模式\n
来多次引用。特殊符号 | 描述 |
---|---|
( ) |
模式内存 |
+*?{} |
出现次数 |
^$\b\B |
锚 |
` | ` |
/
,但其可用字母m
自行指定# An example
m!/u/abc/def/fff! # 等价于
/\/u\/abc\/def\/fff/
'
作为定界符时,不做变量替换$n
,全部的结果用变量$&
。选项 | 描述 |
---|---|
g |
匹配所有可能的模式 |
l |
忽略大小写 |
m |
将串视为多行 |
o |
只赋值一次 |
s |
将串视为单行 |
x |
模式中的空白 |
选项m
^
符号匹配字符串的起始或新的一行的起始,$
符号匹配任意行的末尾选项o
$var = 1;
$line = ;
while ($var < 10) {
$result = $line =~ /$var/o;
$line = ;
$var++;
}
# 每次均匹配/1/ 。
选项s
/a.*bc/s
匹配字符串axxxxx \nxxxxbc
,但/a.*bc/
则不匹配该字符串。语法为:s/pattern/replacement/
,其效果为将字符串中与pattern
相匹配的部分换成replacement
。
在替换部分可使用模式次序变量$n
,如s/(\d+)/[$1]/
,但在替换部分不支持模式的特殊字符,如{},*,+
等
替换操作符的选项
选项 | 描述 |
---|---|
g |
匹配所有可能的模式 |
l |
忽略大小写 |
m |
将串视为多行 |
o |
只赋值一次 |
s |
将串视为单行 |
x |
模式中的空白 |
e |
替换字符串作为表达式 |
# e 选项把替换部分的字符串看作表达式,在替换之前先计算其值,即将字符串重复相应的次数。
$string = "1abc1";
$string =~ s/\d+/$& x 2/e;
# $string = 11abc1
这是另一种替换方式,语法如:tr/string1/string2/
。同样,string2
作为替换部分,但其效果是把string1
中的第一个字符换为string2
中的第一个字符,把string1
中的第二个字符替换为string2
中的第二个字符,依此类推。
$string = "abcdefghicba";
$string =~ tr/abc/def/;
# now string = "defdefghifed"
当 string1
比string2
长时, 其多余字符替换为string2
的最后一个字符
当string1
中同一个字符出现多次时, 将使用第一个替换字符
翻译操作符的选项
选项 | 描述 |
---|---|
c |
翻译所有未指定字符 |
d |
删除所有指定字符 |
s |
把多个相同的输出字符缩成一个 |
PERL 支持PERL4 和标准UNIX 模式匹配操作所没有的一些模式匹配能力。其语法为:(?
,其中c
是一个字符,pattern
是起作用的模式或子模式。
不存贮括号内的匹配内容在 PERL 的模式中,括号内的子模式将存贮在内存中,此功能即取消存贮该括号内的匹配内容, 如/(?:a|b|c)(d|e)f\1/
中的\1
表示已匹配的d
或e
,而不是a
或b
或c
。
内嵌模式的选择
通常模式选项置于其后 , 有四个选项: i 、m、s 、x
可以内嵌使用,语法为: /(?option)pattern/
, 等价于/pattern/option
。
肯定的和否定的预见匹配
肯定的预见匹配语法为/pattern(?=string)/
,其意义为匹配后面为string
的模式, 相反的, (?!string)
意义为匹配后面非string
的模式
$string = "25abc8";
$string =~/abc(?=[0-9])/;
$matched = $&;
print "$matched\n";
# $&为已匹配的模式 此处为abc 而不是abc8
$string = "25abcbd33abc23";
@word = $string =~/abc(?![a-zA-Z])/g;
$count=@word;
print $count."\n";
print "@word\n";
# @word 长度为1,内容为abc
模式注释
Perl5中可以在模式中使用?#
来加注释,如if($string=~/(?i)[a-z]{2,3}(?# match two or three alphabetic characters))/
if ( ) {
}
elsif ( ) {
}
...
else {
}
# 1 、while 循环
while ( ) {
}
# 2 、until 循环
until ( ) {
}
for ($count=1; $count <= 5; $count++) {
# statements inside the loop go here
}
# 下面是在for 循环中使用逗号操作符的例子:
for($line = , $count = 1; $count <= 3; $line = ,$count++)
{
print ($line) ;
}
# 它等价于下列语句:
$line = ;
$count = 1;
while ($count <= 3) {
print ($line);
$line = ;
$count++;
}
foreach
foreach localvar ( list expr ) {
statement_block;
}
# 例:
@words =("the","Xian","Bei","San");
foreach $word (@words) {
if ( $word eq "the" ) {
print ( "found the word 'the'\n" ) ;
}
}
localvar
是个局部变量,如果在此之前它已有值, 则循环后仍恢复该值。do
循环do {
statement_block
} while_or_until (condexpr);
# do 循环至少执行一次循环。
last
,与C中的break
作用相同next
,与C中的continue
作用相同redo
,其含义是重复此次循环,即循环变量不变,回到循环起始点,但redo
命令在do
循环中不起作用goto label;
语句语法为statement keyword condexpr
。其中keyword
可为if、unless、while 或until
$var= 2;
print ("Not zero yet $var.\n") while ($var-- > 1);
print ("This is zero $var. \n " ) if ($var == 0);
print ("This is zero $var.\n") unless ($var != 0);
print ("Not zero yet $var. \n") until ($var-- == -2);
print "the final value is $var\n";
虽然条件判断写在后面, 但却是先执行的
子程序即执行一个特殊任务的一段分离的代码,它可以减少重复代码且使程序易读。
Perl中,子程序可以出现在程序的任何地方。
定义方法为:
sub subroutime{
state ments;
}
用&
调用
&subname;
. . .
sub subname{
. . .
}
先定义后调用,可以省略&
符号(类似C中调用在定义前)
sub subname{
. . .
}
. . .
subname;
前向引用,先定义子程序名,后再定义子程序体(类似C中先声明,后定义)
sub subname;
. . .
subname;
. . .
sub subname{
. . .
}
return(retval)
,retval
可以为列表my
和local
my
定义的变量只在该子程序中存在local
定义的变量不存在于主程序中,但存在于该子程序和该子程序调用的子程序中形式:
&sub1($number1, $number2, $nubmer3 );
. . .
sub sub1{
my($number1, $number2, $number3) = @_;
. . .
}
传递数组
&addlist (@mylist) ;
&addlist ("14", "6", "11");
&addlist ($value1, @sublist, $value2);
...
sub addlist {
my (@list) = @_;
...
}
参数为数组时,子程序只将它赋给一个数组变量。但简单变量和数组变量可以同时传递
sub twolists {
my (@list1, @list2) = @_;
}
# @list2 必然为空。
&twoargs(47, @mylist); #47 赋给$scalar, @mylist 赋给@list
&twoargs(@mylist) ; # @mylist 的第一个元素赋给$scalar,其余的元素赋给@list
. . .
sub twoargs {
my ($scalar, @list) = @_;
. . .
}
用&my_sub(@array)
将把数组@array
的数据拷贝到子程序的变量@_
中,当数组很大时,开销较大,可以使用别名传参,对该数组直接操作(类似C中的传递指针)。形式如下:
@myarray = ( 1 , 2 , 3 , 4 , 5 ) ;
&my_sub(*myarray);
. . .
sub my_sub {
local (*subarray) = @_;
print "@subarray\n";
. . .
}
此方法类似于C 语言中的传递数组的起始地址指针, 但并不一样,在定义数组的别名之后,如果有同名的简单变量,则对该变量也是起作用的。
$foo = 26;
@foo = ("here's" , "a" , " list" ) ;
&testsub (*foo);
sub testsub {
local (*printarray) = @_;
@foo[3] = "of yeshou\n";
$printarray = 61;
}
print $foo."\n"; # 61
print "@foo\n"; # here's a list of yeshou
用别名可以传递多个数组
@array1 = (1, 2, 3);
@array2 = (4, 5, 6);
&two_array_sub (*array1, *array2);
sub two_array_sub {
local(*subarray1, *subarray2) = @_;
print "sub1:@subarray1\tsub2:@subarray2"; # sub1:1 2 3 sub2:4 5 6
@subarray1[3]=114;
@subarray2[3]=514;
}
print "array1:@array1\tarray2:@array2"; # array1:1 2 3 114 array2:4 5 6 514
PERL5 预定义了三个子程序,分别在特定的时间执行,它们是:
BEGIN 子程序在程序启动时被调用;
END 子程序在程序结束时被调用;
AUTOLOAD 子程序在找不到某个子程序时被调用。你可以自己定义它们, 以在特定时间执行所需要的动作。
BEGIN {
print("Hi! Welcome to Xianbei! \n" ) ;
}
AUTOLOAD{
print("subroutine $AUTOLOAD not found\n"); # 变量$AUTOLOAD 即未找到的子程序名
print("arguments passed: @_\n");
}
END {
print "114 514 1414914\n";
}
&test;
# output:
# Hi! Welcome to Xianbei!
# subroutine main::test not found
# arguments passed:
# 114 514 1414914
很难记住哪个元素存贮的什么内容
# an example: find the capitalized words and count.
while($inputline= ){
while($inputline=~/\b[A-Z]\S+/g){
$word = $&;
$word=~s/[;.,:-]$//;
for($count=1;$count<=@wordlist;$count++){
$found=0;
if($wordlist[$count-1] eq $word){
$found=1;
$wordcount[$count-1]+=1;
last;
}
}
if($found==0){
$oldlength=@wordlist;
@wordlist[$oldlength]=$word;
@wordcount[$oldlength]=1;
}
}
}
print ("Capitalized words and number of occurrence:\n");
for($count=1;$count<=@wordlist;$count++){
print ("@wordlist[$count-1]:@wordcount[$count-1]\n");
}
print "\n@wordlist \n@wordcount\n";
# Input:
# Here is a line of Input.
# There Input contains some Capitalized words.
# ^Z
# Output:
# Capitalized words and number of occurrence:
# Here:1
# Input:2
# There:1
# Capitalized:1
# Here Input There Capitalized
# 1 2 1 1
$
符号打头,下标用大括号围起来。创建一个关联数组元素最简单的方法是赋值
如语句$fruit{"bananas"} = 1;
把1 赋给关联数组%fruit
下标为bananas
的元素, 如果该元素不存在, 则被创建, 如果数组%fruit 从未使用过, 也被创建。
# another example
while($inputline= ){
while($inputline=~/\b[A-Z]\S+/g){
$word=$&;
$word=~s/[;.,:-]$//;
$wordlist{$word}+=1;
}
}
print("Capitalized words and number of occurrences:\n");
foreach $capword (keys(%wordlist)){ #内嵌函数keys()返回关联数组的下标列表
print ("$capword: $wordlist{$capword}\n");
}
# Input:
# Here is a line of Input.
# This Input contains some Capitalized words.
# ^Z
# Output:
# Capitalized words and number of occurrences:
# Input: 2
# Here: 1
# This: 1
# Capitalized: 1
关联数组总是随机存贮的,因此当你用keys()
访问其所有元素时,不保证元素以任何顺序出现,特别值得一提的是,它们不会以被创建的顺序出现。
要想控制关联数组元素出现的次序,可以用sort( )
函数对keys()
返回值进行排列,如:foreach $capword (sort keys(%wordlist))
可以用单个赋值语句创建关联数组, 如:
%fruit = ("apples",17,"bananas",9,"oranges","none");
此语句创建的关联数组含有下面三个元素:
下标为apples 的元素, 值为17
下标为bananas 的元素, 值为9
下标为oranges 的元素, 值为none
用列表给关联数组赋值时,Perl5 允许使用"=>“或” , “来分隔下标与值, 用”=>"可读性更好些, 上面语句等效于:
%fruit = ("apples"=>17,"bananas"=>9,"oranges"=>"none");
与列表一样, 也可以通过数组变量创建关联数组, 当然, 其元素数目应该为偶数
@fruit = ("apples",17,"bananas",9,"oranges","none");
%fruit = @fruit;
可以把关联数组赋给数组变量
%fruit = ("grapes",11,"lemons",27);
@fruit = %fruit;
# 注意,此语句中元素次序未定义,那么数组变量@fruit 可能为("grapes",11,"lemons",27)或("lemons",27,"grapes",11)。
关联数组变量之间可以直接赋值, 如: %fruit2 = %fruit1
可以把数组变量同时赋给一些简单变量和一个关联数组变量
关联数组可以通过返回值为列表的内嵌函数或用户定义的子程序来创建
delete
,如:delete($fruit{"lime"});
delete
函数来删除关联数组的元素, 这是唯一的方法。push、pop、shift
及splice
,因为其元素位置是随机的。keys()
函数返回关联数组下标的列表values()
返回关联数组值的列表keys()
函数的foreach
循环语句, 这种循环效率比较低, 因为每返回一个下标, 还得再去寻找其值each()
,each()
函数每次返回一个双元素的列表, 其第一个元素为下标,第二个元素为相应的值, 最后返回一个空列表。each()
循环中添加或删除元素,否则会产生不可预料的后果。open
: 允许程序访问文件close
: 终止文件访问print
: 文件写入字符串write
: 向文件写入格式化信息printf
: 格式化字符串并输出到文件+>
,如:open(READWRITE, "+>file1");
+<
指定可读写权限。print
,printf
和write
函数print
是这三个函数中最简单的, 它向指定的文件输出, 如果未指定, 则输出到当前缺省文件中,若未调用select
, 则为STDOUT
printf
函数先格式化字符串再输出到指定文件或当前缺省文件中select
函数select
函数将通过参数传递的文件变量指定为新的当前缺省文件, 如:select(MYFILE);
eof
函数eof
函数查看最后一次读文件操作是否为文件最后一个记录,如果是, 则返回非零值, 如果文件还有内容, 返回零。eof
的调用不加括号,因为eof
和eof()
是等效的,但与<>
操作符一起使用时,eof
和eof()
就不同了。
eof()
才返回真,如果只是多个文件中前几个的末尾,返回值为假,因为还有要读取的输入。而eof
每读取完一个文件返回值就为真。open
, close
, print
, printf
, write
, select
和eof
,都可以用简单变量来代替文件变量,这时,简单变量中所存贮的字符串就被看作文件变量名open
, close
, write
, select
和eof
还允许用表达式来替代文件变量,表达式的值必须是字符串, 被用作文件变量名。package mypack;
包名 + 双冒号(::) + 变量名
" 的方式指定。package main;
Perl语言提供了两个关键字:BEGIN,END
。它们可以分别包含一组脚本,用于程序体运行前或者运行后的执行。
语法格式如下:
BEGIN{...}
END{...}
每个 BEGIN 模块在 Perl 脚本载入和编译后但在其他语句执行前执行。
•每个 END 语句块在解释器退出前执行。
Perl5 中用Perl包来创建模块。
Perl 模块是一个可重复使用的包,模块的名字与包名相同,定义的文件后缀为 .pm。
# 定义了一个模块 Foo.pm,代码如下所示:
#!/usr/bin/perl
package Foo;
sub bar { print "Hello $_[0]\n" }
sub blat { print "World $_[0]\n" }
1;
Require 和 Use 函数
# use require function
#!/usr/bin/perl
require Foo;
Foo::bar("a");
Foo::blat("b");
# use user function
#!/usr/bin/perl
use Foo;
bar("a");
blat("b");
require
引用需要使用包名指定函数,而 use
不需要
require
用于载入module或perl程序(.pm后缀可以省略,但.pl必须有)use
语句是编译时引入的,require
是运行时引入的use
引入模块的同时,也引入了模块的子模块。而require
则不能引入,要在重新声明use
是在当前默认的@INC里面去寻找,一旦模块不在@INC
中的话,用use
是不可以引入的,但是require
可以指定路径use
引用模块时,如果模块名称中包含::
双冒号,该双冒号将作为路径分隔符,相当于Unix下的/或者Windows下的\。实现方法:
Perl 提供了 bless()
函数,bless
是用来构造对象的, 通过 bless
把一个引用和这个类名相关联,返回这个引用就构造出一个对象。
创建和使用对象
定义方法
# use require function
#!/usr/bin/perl
require Foo;
Foo::bar("a");
Foo::blat("b");
# use user function
#!/usr/bin/perl
use Foo;
bar("a");
blat("b");
require
引用需要使用包名指定函数,而 use
不需要
require
用于载入module或perl程序(.pm后缀可以省略,但.pl必须有)use
语句是编译时引入的,require
是运行时引入的use
引入模块的同时,也引入了模块的子模块。而require
则不能引入,要在重新声明use
是在当前默认的@INC里面去寻找,一旦模块不在@INC
中的话,用use
是不可以引入的,但是require
可以指定路径use
引用模块时,如果模块名称中包含::
双冒号,该双冒号将作为路径分隔符,相当于Unix下的/或者Windows下的\。实现方法:
Perl 提供了 bless()
函数,bless
是用来构造对象的, 通过 bless
把一个引用和这个类名相关联,返回这个引用就构造出一个对象。
创建和使用对象
定义方法