Perl的基本语法 |
前言:
这篇文章是花了我很多时间、费了我很多心血才完成的,虽然连我自己都觉得无法达到尽善尽美的境界,但希望能帮助大家入门,稍微了解到Perl到底是个什麽样的东西,Perl到底有那些强大的功能,那麽这篇文章的目的就达到了。我分做资料型态、控制叙述、副程式、I/O和档案处理、Regular
Expressions、Spectial
Variables、Help
这几部分来讲解,但只是叙述了一些Perl的基本语法而已,Perl活泼的特性和程式的技巧就无法一一详述了,甚为缺憾。
(1) 资料型态(Data
type):
Perl的资料型态大致分为四种:Scalar、Scalar Array、Hash Array、References,看起来虽少但用起来却绰绰有余。尤其在写Perl程式时可以不必事先宣告变数,这一点对刚学程式语言的人甚为方便,不过为了以後程式除错和维护方便,我建议你还是养成事先宣告变数的习惯比较好。
纯量变数是Perl里最基本的一种资料型态,它可以代表一个字元、字串、整数、甚至浮点数,而Perl把它们都看成是一样的东东!
你甚至可以混着用,不可思议吧。例如: 纯量阵列,阵列内的每一个元素都是Scalar variable。宣告及使用方式如下: 杂凑阵列也叫做相关阵列,它和一般阵列没什麽不同,差别只是在它的索引值用的是字串,而非一般阵列所用的整数值,因此相关阵列不像一般阵列一样有次序的概念,它没有所谓的第一项资料这种说法。它就相当於把一堆变数组合成一个group,然後我们可以透过索引字串存取这个group每一个元素的值。相关阵列的宣告及使用方式如下:
Perl有上述三个函数可对相关阵列做运算:keys函数可取出相关变数的索引值,组成一纯量阵列,注意这些由keys函数取出的索引值没有次序性;values函数可取出相关变数的元素值;each函数则会取出(索引、元素)对。使用者可视情况而用。
Perl
5新增了参考指标的资料型态,使Perl和C一样可借由指标建立一些复杂的资料结构。普通程式是用不到指标这玩意的,下面也只是简单介绍一下,看不懂的人可不必深究。
⊙如何取得变数的位址?
Perl 也有和 C 一样以 "\" 开头的特殊字元: 另外需要说明的是 Perl 融合了 unix shell script
的使用惯例,以双引号("")括起来的字串会先经过展开,但反斜线(\)後面的字元则不展开,当作一般字元看待。而以单引号('')括起来的字串完全不会展开,以反单引号(``)括起来的字串会把它当作命令列指令一样执行,等於system()一样。初学者常常会搞混,但习惯之後就会觉得不这样分清楚反而不行哩。举个例吧:
Regular
Expression通常是用来寻找特定的字串样式(pattern),也就是所谓格式辨认(pattern-matching)的功能。它的运算子是『=~』和『!~』,可以把它念做match和not
match。
Syntax: $string =~ /regular expression/expression modifier
例:$sentence =~ /Hello/
例:
例:# 井字号开头的後面都是注解。
#
纯量变数以$开头。
# my 是一种宣告变数的方式,它可以使变数区域化。
# 宣告变数时若不加 my 或 local
则Perl会把它当作全域变数使用。
# 习惯上,我们会将字串用双引号括起来,而数值就不用加引号。
my $x="abc";
my
$x=123;
my $x=4.56;
那麽程式怎麽判断这是数值还是字串呢?
其实不是程式判断,而是你自己要判断。Perl分别提供了一堆运算子来处理数字和字串,你必须知道这个变数是数值或字串,才能使用个别的运算子来对变数做运算。我分别列出字串运算子和数值运算子,好让大家能区分它们的不同。
String Operator
Purpose
x
Returns a string consisting of the string on the left of the operand,
repeated the number of times of the right operand.
.
Concatenates the two strings on both sides of the operator.
eq
Returns True if the two operands are equivalent, False otherwise.
ne
Returns True if the two operands are not equal, False otherwise.
le
Returns True if the operand on the left is stringwise less than the
operand on the right of the operator. Returns False otherwise.
lt
Returns True if the operand on the left is stringwise less than or
equal to the operand on the right of the operator. Returns False
otherwise.
ge
Returns True if the operand on the left is stringwise greater than or
equal to the operand on the right of the operator. Returns False
otherwise.
gt
Returns True if the operand on the left is stringwise greater than the
operand on the right of the operator. Returns False otherwise.
cmp
Returns -1, 0, or 1 if the left operand is stringwise less than, equal
to, or greater than the right operand.
,
Evaluates the left operand, the evaluates the right operand. It
returns the result of the right operand.
++
Increments the string by one alphabetic value.
Value Operator
Purpose
+
Computes the additive value of the two operands.
-
Computes the difference between the two operands.
*
Computes the multiplication of the two operands.
/
Computes the division between the two operands.
%
Computes the modulus(remainder) of the two operands.
= =
Returns Ture if the two operands are equivalent, False otherwise.
!=
Returns Ture if the two operands are not equal, False otherwise.
<=
Returns Ture if the operand on the left is numerically less than or
equal to the operand on the right of the operator. Returns False
otherwise.
=>
Returns Ture if the operand on the left is numerically greater than or
equal to the operand on the right of the operator. Returns False
otherwise.
<
Returns Ture if the operand on the left is numerically less than the
operand on the right of the operator. Returns False otherwise.
>
Returns Ture if the operand on the left is numerically greater than
the operand on the right of the operator. Returns False otherwise.
< = >
Returns -1 if the left operand is less than the right, +1 if is it
greater than, and 0(False) otherwise.
&&
Performs a logical AND operation. If the left operand is True m then
the right operator is not evaluated.
||
Performs a logical OR operation. If the left operand is True m then
the right operator is not evaluated.
&
Returns the valueof the two operators bitwise ANDed.
|
Returns the valueof the two operators bitwise ORed.
^
Returns the valueof the two operators bitwise XORed.
++
Increment operator. Increments the variable's value by 1.
--
Decrement operator. Decrements the variable's value by 1.
**
Computes the power of the left-hand value to the power of the
rihght-hand value.
+=
Adds the value of the right-hand operand to the value of the left-hand
operand.
-+
Subtracts the value of the right-hand operand to the value of the
left-hand operand.
*=
Mlutiplies the value of the left-hand operand to the value of the
right-hand operand.
>>
Shifts the left operand right by the number of bits that is specified
by the right operand.
<<
Shifts the left operand left by the number of bits that is specified
by the right operand.
~
Performs a 1s complement of the operator. This is a unary operator.
# 纯量阵列以 @ 开头。
my @array;
my @array=qw(a b c d);
# qw
函数会将其後的每个元素用逗点隔开,效果就像下面这行。
my @array=("a","b","c","d");
#
当然你也可以一个个元素宣告,下面就是存取每一个元素的方法。
# 因为阵列中的每一个元素都是纯量变数,所以要以 $ 开头,
#
刚开始容易搞混,请注意。
$array[0]="a"; $array[1]="b"; $array[2]="c";
$array[3]="d";
# 使用for loop印出阵列内每个元素的值。
for($i=0; $i<=$#array;
$i++) {
print "$array[$i]\n";
}
看到$#array这个奇怪的东东没?
这是Perl的一个特殊用法,代表这个阵列最後一个元素的注标。由於Perl不必事先宣告变数,也不必预先宣告阵列的大小,甚至可以随时增加新元素,那我们怎麽知道这个阵列到底有多大呢?
透过这个特殊变数我们可以得知这个这个阵列最後一个元素的注标,自然而然也就知道这个阵列究竟有多大了。另外Perl只定义了一维阵列的语法,二维以上只能用指标间接来达成。
# 相关阵列是以 % 符号开头的。
my %hash;
#
=> 这个符号是Perl5新增的,是为了相关阵列量身定做的,
# 因为索引和元素值都是纯量,若使用 => 这个符号,
#
(索引=>元素值) 两两对应,就不容易发生失误。
my
%hash=("i1"=>"aaa","i2"=>"bbb","i3"=>"ccc");
#
上面这行的效果和下面这行是一样的。
my %hash=("i1","aaa","i2","bbb","i3","ccc");
#
下面是存取每个元素的方法,注意是用大括号把索引括起来哦。
# 习惯上索引值用单引号、元素值用双引号括起来。
$hash{'i1'}="aaa";
$hash{'i2'}="bbb"; $hash{'i3'}="ccc";
# 下面是使用相关阵列的三个例子:
foreach $key
(keys %hash) {
print "$hash{$key}\n";
}
foreach $value (values
%hash)
while(($key,$value)=each %hash)
$scalarRef=\$scalarVar;
$arrayRef=\@arrayVar;
$hashRef=\%hashVar;
$funcRef=\&funcName;
print $$scalarRef;
print "@$arrayRef";
print
$hashRef->{$key};
&$funcRef;
$arrayRef=[[1,2,3,4],a,b,[x,y,z],c];
print
"$arrayRef->[0][0]\t$arrayRef->[2]\t$arrayRef->[3][2]\n";
$hashRef={a=>aa,b=>bb,c=>cc};
print
"$hashRef->{a}\t$hashRef->{b}\t$hashRef->{c}\n";
(2) 控制叙述(Control Statements)
# Expression
就是条件叙述式,Perl和C一样没有定义布林资料型态(Boolean data type),
# 因此 0 是false、非0
是ture。另外要注意字串运算子和数值运算子要分清楚哦。
# Code Segment 就是用大括号括起来的一堆指令,也就是一个Block。
if
(Expression) {Code Segment}
if (Expression) {Code Segment} else {Code
Segment}
if (Expression) {Code Segment} elsif (Expression) {Code
Segment} else {Code Segment}
# elsif 就是 else if
#
如果指令(statement)只有一项,我们可以使用倒装句法,看起来比较简洁。
statement if
(Expression);
# unless 就是if not
statement unless
(Expression);
例:
print "HELLO!\n" if ($name eq "friend");
$x-=10 if ($x
== 100);
看吧! C 语言有的Perl大部分都有,学过 C 的人可以毫不费力的学会Perl。
# 注意:纯量变数前面要加个 $ 字号,这一点和C语言不一样哦。
Perl还有提供label(标记)的语法,也就是 goto
指令,不过有经验的programer并不喜欢用它,我也不建议大家使用,所以就此按下不讲。有兴趣的人请自行查阅。还有一点值得注意的是Perl没有提供像C语言一样的
switch 叙述,不过Perl的pattern match的功能非常强,所以我建议你直接用 if else 叙述来做就好了。
for($i=0;
$i<=10; $i++) {Code Segment}
# foreach 是承袭UNIX的shell script来的,
#
第一个引数是纯量变数,第二个引数要用括号括起来,里面是一个纯量阵列,
# 顾名思义它就是把阵列中的每个元素依序传给第一个引数,直到全部传完。
#
它和 for($i=0; $i<=$#array; $i++) 用法虽然不同,但目的都是要取出阵列的每个元素。
foreach $i
(@array) {Code Segment}
# 其实在Perl中,for和foreach是可以混着用的,就看个的人习惯了。
#
下面这行就等於上面第一个叙述,不过简洁多了,大家可以试着用用看。
for $i (0..10) {Code Segment}
#
while控制回圈和後置回圈。
while($i<=10) {Code Segment}
do {Code Segment}
while(Expression);
# Perl也有和C语言的break和continue一样的指令,Perl叫它做 last 和 next
(较口语化)。
#
last是跳出现在所在的回圈,next则是跳过下面的指令直接执行下一次的回圈。
while(chomp($i=<STDIN>))
{
next if ($i == 5);
last unless ($i >
10);
}
(3)
副程式(Subroutines)
my ($a1,$a2,$a3,...) = @_;
来取出各个参数,当然 my @arg=@_;
或 my %arg=@_;
也是可以的。由於Perl的语法非常活泼,使得程式在维护时特别棘手,因此写注解成为一项很重要的工作。我建议你最好在每个副程式前面加上对这段副程式的描述,特别是需要传递的参数要注明清楚。
my
$x=3;
,若副程式所用的变数名不小心和主程相同,Perl会以目前正在执行的副程式里的变数为优先。
(4) I/O和档案处理
close(FILEHANDLE);
Expression
Effect
open(FH, "<filename")
Opens filename for reading.
open(FH, "+<filename")
Opens filename for both reading and writing.
open(FH, ">filename")
Opens filename for writing.
open(FH, "+>filename")
Opens filename for both reading and writing.
open(FH, ">>filename")
Appends to filename.
open(FH, "command|")
Runs the command and pipes its output to the filehandle.
open(FH, "command|")
Pipes the output along the filehandle to the command.
open(FH, "-")
Opens STDIN.
open(FH, ">-")
Opens STDOUT.
open(FH, "<&=N")
Where N is a number, this performs the equivalent of C's fdopen for
reading.
open(FH, ">&=N")
Where N is a number, this performs the equivalent of C's fdopen for
writing. 例:
# 开启$filename这个档案,若开启失败则印出die後面的讯息,并结束程式。
open(FILE,
$filename) || die "Can't open file $filename : $!\n";
# 下面是一个十分精简的写法,和
while($_=<FILE>){print "$_";} 是等效的。
print while(<FILE>);
#
档案开启後要记得随手关闭,这才是写程式的好习惯。
close(FILE);
#
$!和$_都是Perl的特殊变数,下面会介绍的。
#
Perl不会自动去掉结尾的CR/LF,跟C语言不同,所以要用chomp函数帮你去掉它。
#
大家常常会忘记这个动作,导致结果跟你想的不一样,要特别注意一下。
$input=<STDIN>; chomp $input;
#
下面是较简洁的写法。
chomp($input=<STDIN>);
# 不用再指定变数的data
type,这样不是比printf()方便多了吗?
print "Scalar value is $x\n";
# .
是字串加法的运算子,上下这两行是等效的。
print "Scalar value is " . $x . "\n";
#
输出到档案的方法。
print FILE "print $x to a file.";
# 下面是print的特殊用法,学自shell
script的用法:
print<<XXX;这招叫做 here document,XXX可以是你取的任何识别字,
在识别字之间的字都会按照你所写的样子输出,就像<pre>标签一样。
而当一行的开头是XXX你取的这个识别字时,才会停止输出。
XXX \t tab
\n newline
\r return
\f form feed
\b backspace
\a alarm(bell)
\e escape
\033 octalchar
\x1b hex char
\c[ control char
\l lowercase next char
\u uppercase next char
\L lowercase till \E
\U uppercase till \E
\E end case modification
\Q quoteregexp metacharacters till \E
$x="ls -l";
print "$x"; # Output ls -l
print "\$x"; # Output $x
print '$x'; # Output $x
print `$x`; # Output files in this directory
(5) Regular
Expressions
g
Match globally, i.e. find all occurrences.
i
Makes the search case-insensitive.
m
If the string has new-line characters embedded within it, the
metacharacters ^ and $ will not work correctly. This modifier tells Perl
to treat this line as a multiple line.
o
Only compile pattern once.
s
The character . matches any character except a new line. This modifier
treats this line as a single line, which allows . to match a new-line
character.
x
Allows white space in the expression.
\
Tells Perl to accept the following characters as a regular character;
this removes special meanings from any metacharacter.
^
Matches the beginning of the string, unless /m is used.
.
Matches any character except a new line character, unless /s is used.
$
Matches the end of the string, unless /m is used.
|
Expresses alternation. This means the expressions will search for
multiple patterns in the same string.
( )
Groups expressions to assist in alternation and back referencing.
[ ]
Looks for a set of characters.
*
Matchs 0 or more times.
+
Matchs 1 or more times.
?
Matchs 0 or 1 times.
{n}
Matches exactly n times.
{n,}
Matches at least n times.
{n,m}
Matches at least n times but no more than m times.
\r
Carriage return(CR), ASCII 13(十进位)
\n
New line, UNIX中代表ASCII 10(十进位), DOS(Windows)系统中则是ASCII 13 + ASCII
10(十进位).
\t
Tab, ASCII 9(十进位)
\w
Matches an alphanumeric character. Alphanumeric
also includes _. 即 [A-Za-z0-9_].
\W
Matches a nonalphanumeric character. 即 [^A-Za-z0-9_].
\s
Matches a white space character. This includes space,
tab, FormFeed and CR/LF. 即 [\ \t\f\r\n].
\S
Matches a non-whote space character. 即 [^\ \t\f\r\n].
\d
Matches a digit. 即 [0-9].
\D
Matches a nondigit character. 即 [^0-9].
\b
Matches a word boundary.
\B
Matches a nonword boundary.
\033
octal char
\x1B
hex char
/abc/
/^abc/
/abc$/
/a|b/
/ab{2,4}c/
/ab*c/
/ab+c/
/a.c/
/[abc]/
/\d/
/\w/
/\s/
/[^abc]/
/\*/
/abc/i
/(\d+)\.(\d+)\.(\d+)\.(\d+)/
if ($x =~ /(\d+\.\d+)\.\d+\.\d+/) {
print
"海洋大学" if ($1 eq "140.121");
}m//gimosx
$url="my.machine.tw:8080/cgi-bin/test.pl";
这个Regular
Expression相当复杂,主要目的是分析指定的URL,然後取得host名称、port号码及对应的档案。我一项项慢慢解释:
($host, $port,
$file)=($url=~m|http://([^/:]+):{0,1}(\d*)(\S*)$|);
$url=~m||
m後面跟着的就是分隔符号,|
|里面的就是pattern。
([^/:]+)
match一个字串,里面没有/和:字元。找到的字串存在$1中。
:{0,1}(\d*)
match
0或1个:,後面跟着一串数字或nothing。找到的字串存在$2中,若找不到,$2就是空的。
(\S*)$
match一串非空白字元,并以找到的字串为结尾。找到的字串存在$3中。
()=()
($host, $port,
$file)=($1, $2,
$3)
即$host="my.machine.tw"
$port=8080
$file="/cgi-bin/test.pl"
s/PATTERN/REPLACEMENT/egimox
e
Evaluate the right side as an expression.
g
Replace globally, i.e. all occurrences.
i
Do case-insensitive pattern matching.
m
Treat string as multiple lines.
o
Only compile pattern once.
s
Treat string as single line.
x
Use extended regular expressions. $x =~
s/\s+//g
把所有的white space全部去除掉
$x =~ s/([^ ]*):*([^
]*)/$2:$1/
把用":"分开的两个栏位互相对调
$path =~
s|/usr/bin|/usr/local/bin|
它也可以让你自订分隔符号哦
tr/SEARCHLIST/REPLACEMENTLIST/cds
c
Complement the SEARCHLIST.
d
Delete found but unreplaced characters.
s
Squash duplicate replaced characters. $x =~
tr/this/that/
把"this"替换成"that"
$x =~
tr/a-z/A-Z/
把小写字母全部替换成大写字母
$count = $x =~
tr/*/*/
计算$x中有几个"*"