Perl 的理念:There is more than one way to do it!
一,简介
1,Perl的敘述句是用分号(;)隔开的
2,Perl是以井字号(#)作为代码的註解标示,也就是只要以井字号开始,到敘述句結束前的內容都会被当成注解
二,变量 $
1,Perl的单引号中,是无法使用像/n(换行字元),/t(跳格字元)这些特殊字元的(不会被解释)
Perl的双引号中,能解释这些字符:
例如: $c = "在/tPerl/t中使用字串非常容易";
$d = '在/tPerl/t中使用字串非常容易';
print "$c/n"; # 在 Perl 中使用字串非常容易
print "$d/n"; # 在/tPerl/t中使用字串非常容易
2,连接两个字串,用符号 “ . ”,将两个字串相加用“ + ”
#!/usr/local/bin/perl
$a = "number";
$b = 3674;
$c = "4358";
$d = $a.$b;
$e = $b+$c;
$m = "string"
print "$d/n"; #number3674
print "$e/n"; #8032
print $a.$m; #numberstring
print $a+$m; #0
3,如果在定义一个变量没有给定初始值时,则会被认为 undef. 函数defined($name)
4,<STDIN>:
my $num = <STDIN>;
chomp($num);
三,阵列 @
1,Perl 的阵列结构:例如你可以定义一个变量名叫做 @array。然后利用 $array[0],$array[1]...的方式存取阵列里的元素
定义方式:
1)
my @array;
$array[0] = 'first';
$array[1] = 'second';
$array[2] = 'third';
2)
my ($array[0], $array[1], $array[2]) = qw/first second third..../;
3)
my @array = qw/first second third/;
4)
my @array = qw{first second third};
2,$#array #取得阵列的最后一个索引值(这里指的是索引值,而不是阵列的最后一个元素的值,一般都为数字,比如0,1,2,...)
$array #输出的是阵列的长度。
所以我们可以利用($#array + 1)得到目前陣列中的元素個數,其实就等于$array
($#array + 1) = $array
3,push, pop:从阵列的后面(尾)对阵列进行运算
my @array = qw{first second third};
my @array2 = qw/fourth fifth/;
push @array, @array2;
print @array;
输出为:firstsecondthirdfouthfifth
4,shift/unshift:从阵列的前面(头)对阵列进行运算
my @array = (1...10);
shift @array; # 我把1拿掉了
unshift @array, 0; # 現在補上0
print @array; # 現在陣列的值變成了(0, 2...10)
Next:
my @array = (1...10); # 我們還是使用這個陣列
shift @array; # 我把1拿掉了
print "$_/t$array[$_]/n" for (0...9); # 現在陣列的值變成了(0, 2...10)
0 2, 1 3, 2 4, 8 10, 9
** 需要注意上面代码中最后一句print "$_/t$array[$_]/n" for (0...9); $_表示的是for循环里的每一个值。
5,生鱼切片:
my @array = (0...10);
my @array2 = @array[2...4];
print @array2; # 沒錯,你拿到了(2, 3, 4) 三個元素
以上用法称之为切片儿
6,sort:排序
my @array = qw/45 33 75 21 38 69 46/;
@array = sort { $a <=> $b } @array;
這樣Perl就會幫我們把陣列重新排列成為
21 33 38 45 46 69 75
其實,如果你這樣寫也是有相同的效果:
@array = sort @array;
當然,如果你需要比較複雜的排序方式,就要把包含排序的區塊加入,所以你也可以寫 :
@array = sort { $b <=> $a } @array;
其中$a跟$b是Perl的預設變數,在排序時被拿來作為兩兩取出的兩個數字。而<=>則是表示數字的比較,如果陣列中的元素是字串,則必須以cmp來進行排序。
复杂一些还可以这样写:
@array = sort { ($a**2) <=> ($b**2) } @array; # 這次我們以平方進行排序
7,join 与 split:
把串列裡面的元素值用某種方式連接成一個字串:
print join ',', qw/-4 45 -33 8 75 21 -15 38 -69 46/;
8,map:
所謂map就是把陣串列裡的元素一一提出,並進行運算,然後得到另外一個串列,我們就把所得到的串列放到陣列中.
my @array = map { sqrt($_)*10 } qw/45 33 8 75 21 15 38 69 46/; #开平方乘以10
67.0820393249937
57.4456264653803
28.2842712474619
86.6025403784439
45.8257569495584
38.7298334620742
61.6441400296898
83.0662386291807
67.8232998312527
9,grep: 對串列進行篩選
my @array = qw/6 -4 8 12 -22 19 -8 42/; # 指定一個串列給陣列 @array
my @positive = grep {$_ > 0} @array; # 把@array裡大於零的數字取出
print "$_/n" for @positive; # 印出新的陣列 @positive
四,控制结构:
1,区块{}跟变量的应用:
my $a = 3;
my $b = 9;
{
print "$a/n"; # 屬於外層的區塊,所以你會看到 3
my $b = 6; # 定義了這區塊內自己的變數
print "$b/n"; # 於是你看到的這個$b的值其實是6
}
{
print "$a/n"; # 這個區塊沒有自己的$a
print "$b/n"; # 也沒有自己的$b
# 所以你在這裡看到的值其實是上一層的變數值
}
print "$a/n"; # 這裡似乎毫無疑問
print "$b/n"; # Perl還是印出期待中的3跟9
2,if 跟 unless
if (!($a < 3)) 等于 unless ($a <3)
3, 一行的判斷
if ($num < 5) {
$num++;
}
等于这一句: $num++ if ($num < 5);
while (1) { # 在這裡,程式會得到永遠的真值
print "這是無限迴圈";
}
等于这一句:print "這是無限迴圈" while (1);
4,呵呵,经典的计算阶乘的例子:
my $num = 1;
my $result = 1; # 小心,這裡一定要指定$result為1
while ($num <= 10) { # 確定你是否超過範圍
$result*=$num;
$num = $num + 1;
}
另一种写法:
my $result = 1;
for (my $num = 1; $num <= 10; $num = $num + 1) {
$result *= $num;
}
5,Perl的神奇写法:
for my $num (1...10) { # 這就是表示$num從1到10
print $num;
}
這其實可以寫成:
for (1...10) { # $_ 經常被拿來作為迴圈的預設變數
print $_;
}
更簡化的寫法:
print for (1...10);
6,foreach 函数:
my @array = qw/1 2 3 4 5/;
for (my $i = 0; $i < $#array; $i++) {
print $array[$i];
}
等同于: print foreach (@array); foreach my $element (@array);
7,my @array = qw/6 -4 8 12 -22 19 -8 42/;
my @positive;
for (@array) { # 針對陣列的每個元素檢察
push @positive, ($_**2) if ($_ > 0); # 如果大於零就取平方值
}
print for (@positive);
等同于:
my @array = qw/6 -4 8 12 -22 19 -8 42/;
my @positive = map { $_**2 } grep { $_ > 0 } @array;
# 倒裝,把@array的元素先放進 grep 檢查,再把通過檢查的結果利用map取得平方值放 進新的陣列
五, Hash %
1, Hash % 赋值:
1) my %hash = qw/1 one 2 two 3 three/;
2) my %hash = (1, 2, 3, 4, 5);
3) my %hash = (
1 => 'one',
2 => 'two',
3 => 'three',
);
2, each 函数:
每次each函數都会返回一个包含两个元素的阵列,其中这两个值分别是一个HASH的键值跟Value。
my %hash = (
'168.1.2.1' => 'verdi',
'192.1.2.2' => 'wagner',
'168.1.2.3' => 'beethoven',
); # 定義主機跟ip 的對應
my @hostname;
while (my ($key, $value) = each (%hash)) {
if ($key =~ /^192/) { # 要找出ip以192開頭的部份
push @hostname, $value; # 找到之後放入新的陣列中
}
}
print @hostname;
3,Hash的Key函数跟Value函数的用法:
把key或者value放到同一个阵列中:
my @keys = keys(%hash); my @values = values(%hash);
4,exists
print "exist" if (grep { $_ eq 'video' } keys (%hash));
等于: print "exists" if (exists $hash{video});
5,delete
delete $hash{video}; 将hash表中的一对值删除,包括键值跟value.并不是undef的概念.
六, 子函数 &
(有些地方叫做副常式,个人认为就是个子函数)
1, 表现方式,调用时可以加&,也可以不加, 且可以放到代码的任何地方.例如:
my $num = 12;
print hex($num),"/n"; # 這是Perl提供的hex函式
print &hex($num),"/n"; # 我們自己寫的hex副常式
sub hex {
my $param = shift;
$num*2;
}
2,参数的使用:
&hello("world"); # 傳參數"world"
sub hello {
my $name = shift @_; # 把參數從預設陣列拿出來
print "hello $name/n"; # 根據參數不同印出不同的招呼
}
3,返回值,return
my $return = &adv(4, 2, 6, 4, 9); # 我們一次傳入五個參數
print $return;
sub adv {
my $total;
for (@_) { # 針對預設陣列進行運算
$total += $_; # 加總
}
$total/($#_+1); # 除以總數 (取平均)
}
4, 比较local与my的不同用法:(看例子意会吧,不做解释了)
$var1 = "global";
$var2 = "for local";
&sub1; # var1=local var2=for local
&sub2; # var1=golbal var2=for local
sub sub1 {
local $var1 = "local";
my $var2 = "my";
&sub2;
}
sub sub2 {
print "var1=$var1/tvar2=$var2/n";
}
七, 深入控制结构
1,last: 最后
for (1...10) {
last if ($_ == 8);
print; # 這樣會印出 1...7
}
2,redo
for (1...10) {
$_++; # redo 其實會來這裡
redo if ($_ == 8); # 我們希望 redo 的條件
print; # 會印出 2, 3, 4, 5, 6, 7, 9, 9, 10, 11
}
这时需要注意for (1...10)的用法,它就相当于for (my @array = (1...10))
for ($_ = 1; $_ <= 10; $_++) {
$_++; # 我們還是先把得到的元素進行累加
redo if ($_ == 8); # 遇到8的時候就重複一次
print $_; # 印出目前的 $_,我們得到2, 4, 6, 9, 11
}
redo 会去重复循环内部的命令
3,next
for (1...10) {
next if ($_%2); # 以串列值除以2的餘數判断,余数为0时,也就是偶数时,IF条件为假.余数为1时,IF条件为真,执行下面的命令。
print $_;
}
4,标识
LABEL: for my $outter (1...5) {
for (1...10) {
if ($_ > 2) { next LABEL; } else { print "inner $_ /n"; }
}
next LABEL if ($outter%2);
print $_;
}
5,switch
if (..){ $case=1; }
if (..){ $case=2; }
if (..){ $case=3; }
switch:{
if ($case=1){...}
if ($case=2){...}
if ($case=3){...}
}
6, 三元运算符 ?
my ($a, $b) = (42, 22);
my $max = ($a > $b) ? $a : $b;
print "$max/n";
7, || 运算符
sub input {
my $key = shift || "預設值";
print "$key/n";
}
八,正则表达式基本性质 =~
m//, //,m{}, m||, m!!
1)比对单一的字符串
my $answer = "monger";
until ((my $patten = <STDIN>) =~ /$answer/) {
# 持續進行,直到使用者輸入含有 monger 的字串
print "wrong/n"; # 在這裡,表示比對失敗
};
2) * 可以比对0到任何次, 也就是匹配的概念
my $answer = "mo*r"; # 使用量詞
while (1) { # 所以其實是無限迴圈
if ((my $patten = <STDIN>) =~ /$answer/) { # 判斷是否比對成功
print "*match*/n";
} else {
print "*not match*/n";
}
};
3) + 可以匹配1到任何次,不能匹配0次,比如"mr"是不能比对出来的.
my $answer = "mo+r";
4) {min, max} 可限制比对的次数
my $answer = "mo{2,4}r";
当然还可以省略掉其中的一个限制,比如{min,}{3,},表示3次或3次以上
{,max}{,8}表示出现8次或者8次以下.
5) () 如果想比对一串字符,而不单单是一个字符时,用小括号括起来.
my $answer = "(wow)+"; 比较字符串中是否还有wow这串字符
九, 正则表达式更多概念
1) 正则表达式中的 "或 |"
/f(oo|ee)t/ # 找 foot 或 feet
/it (is|was) a good choice/ # 在句子中用不同的字
/on (March|April|May)/ # 顯然也可以多個選擇
2) 集合 []
(/a|b|c|d|.......|z|A|B|C|D|......|_|) = [a-zA-Z_]
集合中的特殊字元,-,^:
在一个集合中比对“-”的时候前面必须加上转义字符“/” 例如要比对符号[!@#$%^&*()
_+/-=]
在一个集合中,将“^”放到开头表示排除,例如 [^24680] 表示比对24680以外的字元
3) 特殊符号
/s:比对空白字符,可以处理(/n:换行 /t: 跳格TAB /f:换页 /r:回行首 )這五种字符留下的空白痕迹
/S:在大部份的時候,正则表达式特殊字符的大小写总是表示相反的意思,例如我们使用/s來表示上面所说的五种空白字符,那么/S也就是排除以上五种字符。
/w:等于[a-zA-Z]的集合,例如你可以比对长度为3到10的英文单字,那就要写成:
/w{3,10},同樣的,你就可以比對英文字母或英文單字了。
/W:同样的,如果你不希望看到任何在英文字母范围里的字符,就用/W。
/d:等于[0-9]的集合。
/D:[^0-9]:)
例如:[a-zA-Z0-9_] = [/d/w_]
4)/i : 忽略大小写
$content =~ /perl/; 查找小写的
$content =~ /Perl/; 查找大写的
$content =~ /[pP]erl/; 查找大小写的
$content =~ /perl/i; 也是查找大小写的
5)my $content = "I like perl. /n I am a perl monger. /n";
if ($content =~ /(like.*monger)/s) {
print "$1/n";
}
. :萬用字元點號(.)
$1:Perl的预设参数用来贮存比对的结果,如($1, $2, $3...)
6)Perl分配变量的方式則是根据左括号的位置来进行的。
my $content = "I like perl. /n I am a perl monger. /n";
if ($content =~ /((perl)/s(monger))/s) {
print "$1/n$2/n$3/n";
}
输出:
perl monger
perl
monger
7)^ 表示字串开始的时候。$ 表示字串结束的时候。
/^Perl/ :希望比對某個字串一开始就是"Perl"这个字串儿, Perl is good.
/Perl$/ :希望比對某個字串结束时才是"Perl"这个字串儿, This is a Perl.
在一个集合中,将“^”放到开头表示排除,例如 [^24680] 表示比对24680以外的字元
十,正则表达式中的替换 s///
s///来表示替換,其中第一部份表示比对的字串,第二部份则是要进行替换的部份
s/比对的字串/替换的部份/
1) /g 表示全部替换
my $content = "水果對我們很有幫助,所以應該多吃水果";
print $content if ($content =~ s/水果/零食/); # 把水果用零食置換
my $content = "水果對我們很有幫助,所以應該多吃水果";
print $content if ($content =~ s/水果/零食/g); # 把水果全部換成零食吧
如果希望不管大小写替换,还可以加i, 如 /gi
2) 一个互相交换的例子
my $string = "lwh shi ge hao hai zi, ni shi ge huai hai zi";
print $string if ($string =~ s/(lwh)(.*)(ni)(.*)/$3$2$1$4/);
3)(?)來表示不贪多
my $string "<table><tr><td>first</td></tr><tr><td>second</td></tr><tr><td>
third </td></tr></table>";
if ($string =~ m|<tr><td>(.+?)<//td><//tr>|) {
print "$1";
}
比对的结果竟然是 first, 为啥不是<tr><td>first</td></tr><tr><td>second</td></tr><tr><td>
third </td></tr>呢? 真奇怪???
4)比对技巧,回溯參照 (backreference)
不是很懂,有待学习。