全部博文(178)
分类: LINUX
2008-09-10 14:13:30
但严格意义上讲,列表是指数据,
而数组是其变量名。可以有一些值(列表)但不属于数组;但每一个数组标量都有一个列表,虽然其可以为空
$fred[0] = “yabba”;
$fred[1]= “dabba”;
$fred[2] = “doo”;
数组名字(本例中:fred)和标量是属于完全不同的命名空间(namespace)。同一程序也可以同时包含叫做$fred 的标量变
量。Perl 将它们当作完全不同的事物来看待,不会混淆◆。(但维护人员可能混淆,所以最好不要将它们以相同的名字来命名.
实际上是绝大多数。最明显的例外是foreach 循环中的控制变量(在本章后面将介绍到), 必须是标量变量.
最后一个元素的索引为$#rocks ,它比数组的个数始终会少1 。
列表。(“fred”, “barney”, “betty”, “wilma”, “dino”)
($m+$o,$p+$q) #两个值
(1 ..5) #同(1,2,3,4,5)
(1.7..5.7) #同上— 最小值和最大值被转换成整数
(5 ..1) #空列表— ..中的左值应小于右值,否则为空
(0,2 .. 6,10,12)#同(0,2,3,4,5,6,10,12)
($m ..$n) #由$m 和$n 的值决定
(0 .. $#rocks) #上节中有$#rocks 的介绍
qw 简写qw(fred barney betty wilma dino ) #同上,但输入更少
Perl 允许使用任何标点符号作为分界符
qw ! fred barney betty wilma dino !
qw# fred barney betty wilma dino # #有些像注释
qw( fred barney betty wilma dino )
qw{ fred barney betty wilma dino }
qw[ fred barney betty wilma dino ]
qw< fred barney betty wilma dino >
如后面四个例子中显示的那样,有时两个分界符
qw!Yahoo\! Google excite lycos ! #其中一个元素为:字符串yahoo!
push pop
@array = 5..9;
$fred = pop(@array); #$fred 得到9,@array 现在为(5,6,7,8)
$barney = pop @array; #$barney gets 8, @array 现在为(5,6,7)
pop @array; #@array 现在为(5,6)(7 被丢弃了)
最后一个例子中,pop 使用在“in a void context”,也就是说没有存放其返回值的地方。这样使用pop 是合法的。
push(@array,0); #@array 现在为(5,6,0)
push @array,8; #@array 现在为(5,6,0,8)
push @array,1..10; #@array 现在多了10 个元素
@others =qw/9 0 2 1 0 /;
push @array,@others; #@array 现在又多了5 个元素(共有19 个)
shift 和unshift 操作
push 和pop 对数组的末尾进行操作(或者说数组右边有最大下标的元素,这依赖于你是怎样思考的)。相应的,unshift 和
shift 对一个数组的开头进行操作(数组的左端有最小下标的元素)。下面是一些例子:
@array = qw# dino fred barney #;
$m = shift (@array); #$m 得到“dino”, @array 现在为(“fred”, “barney”)
$n = shift @array; #$n 得到”fred”, @array 现在为(“barney”)
shift @array; #@array 现在为空
$o = shift @array; #$o 得到undef, @arry 仍为空
unshift(@array,5); #@array 现在为(5)
unshift @array,4; #@array 现在为(4,5)
@others = 1..3;
unshift @array, @others; #array 现在为(1,2,3,4,5)
和pop 类似,如果其数组变量为空,则返回undef。
3.5 将数组插入字符串
@array2=qw("xiao is love yuang now ");
print "@array2\n";
print " I am xiao ,@array2\n";
I am xiao ,"xiao is love yuang now "
和标量类似,数组也可以插入双引号的字符串中。插入的数组元素会自动由空格◆分开:
◆分隔符是变量$’’的值,其默认值为空格(space)。
@rocks = qw{ flintstone slate rubble };
print “quartz @rocks limestone\n”; #输出为5 种rocks 由空格分开
插入的数组元素的第一个元素前面和最后一个元素后面不会插入空格,如果需要可以自己加入:
print “Three rocks are: @rocks.\n”;
print “There’s nothing in the parens (@empty) here..\n”;
如果忘了数组插入的规则,当把email 地址插入双引号字符串时可能出现意想不到的结果。由于历史原因◆,这将引起编
需要反斜扛转义的有"" 中 @ $ {}
只有一个元素的数组的被其值替换的行为和你预期的类似:
@fred = qw(hello dolly);
$y = 2;
$x =“This is $fred[1]’s place”; # “This is dolly’s place”
$x =“This is $fred[$y-1]’s place”; #同上
索引表达式被当作普通表达式求值,看起来和不在字符串中是一样的。其变量不会首先被赋值的。换句话说,如果$y 为“2*4”,
那上述表达式的值为1,而非7,因为“2*4”首先当作数字时($y 在数字表达式中)为2◆。如果想在一个标量变量后接一
个左中括号符,那应当在其间加入分隔符,否则会被作为数组看待:
◆当然,当把警告打开时,Perl 会提醒你“2*4” 是一个funny-looking 数字。
@fred = qw(eating rocks is wrong);
$fred = “right”; #我们将打印“this is right[3]”
print “this is $fred[3]\n”; #打印出“wrong”使用$fred[3]
print “this is ${fred}[3]\n”; #打印出“right”(由花括号分开)
print “this is $fred”. “[3]\n”; #正确(两个字符串,右. 分开)
print “this is $fred\[3]\n”; #正确(利用反斜线转义)
3.6.1 Perl 最常用的默认变量:$_
如果在foreach 循环中省略了控制变量,那Perl 会使用其默认的变量:$_。除了其不寻常的名字外,这和普通变量类似,如
下面代码所示:
foreach(1..10){ #使用默认的变量$_
print “I can count to $_!\n”;
}
虽然它不是Perl 中唯一的默认变量,但无疑是使用的最普遍的。你将在许多例子中看到Perl 在没有要求它使用某个变量或
值时,会自动使用变量$_,这将节约程序员大量的时间来思考使用哪一个变量。为了消除你的疑虑,下面的print,就是使
用$_的一个例子:
$_ =“Yabba dabba doo\n”;
print; #打印出默认变量$_。
reverse 操作
reverse(逆转)操作将输入的一串列表(可能是数组)按相反的顺序返回。如果不喜欢范围操作符: ..,只能从小到大,
那可以使用reverse 来解决这个问题:
@fred = 6 ..10;
@barney = reverse (@fred); #得到10,9,8,7,6
@wilma = reverse 6 ..10; #同上,没有使用额外的数组
@fred = reverse @fred; #将逆转过的字符串存回去
注意最后一行,其中@fred 使用了2 次。Perl 通常先计算变量的值(赋值号右边),再进行赋值。
注意reverse 返回逆转的列表,它不会改变其参数的值。如果返回值没有赋值给某个变量,那这个操作是没有什么意义的:
reverse @fred; #错误,没有改变@fred 的值
@fred = reverse @fred; #改变了@fred 的值
sort 操作
sort 操作将输入的一串列表(可能是数组)根据内部的字符顺序进行排序。如对于ASCII 字符串,将根据ASCII 序进行排
序。当然,ASCII 中有一些奇怪的地方,如大写字母在小写字符的前面,数字在字符的前面,而标点符号散布在各处。但
按ASCII 排序只是其默认的行为,在第十三章中,可以看到如何按你想要的顺序进行排序的方法:
@rocks = qw/ bedrock slate rubble granite /;
@sorted = sort(@rocks); #得到bedrock, granite, rubble, slate
@back = reverse sort @rocks; #为slate 到bedrock
@rocks = sort @rocks; #将排序的值写回@rocks
@numbers = sort 97 ..102; #得到100,101,102,97,98,99
从最后一个例子可以看到,如果将数字按照字符串进行排序可能得到没有意义的结果。当然,默认的排序规则下,任何由
1 开头的字符串先于由9 开头的字符串。和reverse 一样,其参数是不会受到影响的。如果想将某个数组排序,那必须将排
序之后的结果存回数组中:
sort @rocks; #错误,不会修改@rocks
@rocks = sort @rocks; #现在@rocks 值是经过排序的
@people = qw( fred barney betty );
@sorted = sort @people; #列表context:barney , betty, fred
$number = 42 + @people; #标量context:42+3,得到45
其用法是显然的:如果一个表达式不是列表值,则标量值自动转换为一个元素的列表:
@fred = 6*7;
@barney = “hello”. ‘’. “world”;
第四章子程序
sub marine {
$n + = 1; #全局变量$n
print “Hello, sailor number $n!\n”;
}
返回值
sub sum_of_fred_and_barney{
print “Hey, you called the sum_of_fred_and_barney suroutine!\n”;
$fred + $barney; #返回值
}
子程序中最后一个被计算的表达式为$fred + $barney,因此$fred 和$barney 的和将被返回
此参数列表被传到子程序中;这些参数可以被子程序使用。当然,这些参存放在某个地方,在Perl 中,会自动将此参数列
表(此参数列表的另一个名字)自动存放在一个叫做@_的数组中。子程序可以访问次数组变量来确定此参数的个数以及
其值。第一个值存放在$_[0]中,第二个存放在$_[1]
依次类推。但必须强调的是这些变量和$_这个
变量没有任何关系,如$dino[3](数组@dino 的一个元素)和$dino 的关系一样
sub max{
#和&larger_of_fred_or_barney 比较
If($_[0] > $_[1]){
$_[0];
}else{
$_[1];
}
}$n = &max(10,15,27); #oops!额外的参数被忽略了;因为此子程序不会使用$_[2],Perl 不会关心是否有多余的变量
子程序中的私有变量
my($m,$n) = @_;
上面的一条语句创建了一些私有变量并给它们赋值,第一个为$m,第二个为$n。几乎每一个子程序都由类似的语句开头。
当看见那一行时,你就知道此子程序需要2 个变量,在此子程序中非别被叫做$m 和$n。sub max {
my($m,$n); #新的,私有变量
($m,$n) = @_; #赋值
if($m > $n) {$m} else{$n}
}
子程序可以容易的检测@_是否含有恰当的个数。例如 if (@_!-=2){...}
#!/usr/bin/perl -w
print "the max subroutines============================\n";
sub max{
my($n)=shift @_; #第一个元素是$n=$_[0];
foreach
{
if($_>$n)
{
$n=$_;
}
}
$n;
}
$M=&max(20,30);
print "$M\n";
当然,my 操作不会改变赋值参数的context:
my ($num) = @_; #列表context, 同($sum) = @_;
my $num = @_; #标量context,同$num = @_;
在第一个例子中,$num 得到第一个参数,因为其在列表context 中;第二个例子中,将得到参数的个数,因为是在标量context
中。两条语句都可能是正确的;不能仅凭它来判断是否使用错误,因此Perl 不能提示(warning)你,如果你使用错误。(当
然,不能将这两天语句写在同一个子程序中,因为不能在一个作用域内重复定义某个变量)。当读到这样的代码时,可以通
过上下文来判断其context。
use strict; #迫使采用更严格的检测
#!/usr/bin/perl -w
@name=qw/ xiaone cry is lovers /;
sub which{
my($wh,@arr)=@_;
foreach(0..$#arr)
{
if ($arr[$_] eq $wh)
{
return $_;
}
}
return -1;
}
$yes=&which("xiaone",@name);
print "do have search now:$yes\n";
第五章输入与输出
一\标准输入设备输入
:
chomp($line=
行输入操作在到达文件的结尾时将返回undef,这对于从循环退出时非常方便的:
while (defined($line =
print “I saw $line”;
}
第一行代码值得仔细说明:我们将输入的字符串读入一个变量,检查其是否defined,如果是(意味着我们没有到达输入的
结尾),则执行while 的循环体。因此,在循环的内部,我们将看到每一行,一行接着一行◆。你可能经常进行此类操作,
因此Perl 提供了一种简写方式。如下:
◆你可能注意到我们没有对输入的字符串进行chomp 操作。在这种类型的循环中,你不能将chomp 操作插入条件表达式中,因此这通常是循
环体的第一条语句。我们将在下一节中见到此类例子。
while(
print “I saw $_”;
}
为了得到这种简写,Larry 使用了一些无用的语法(useless syntax)。也就是说: “读入一行输入,看其是否为真(通常为真)。
如果为真,则进入while 循环,然后丢掉它!”。Larry 知道很少有人这样做;没人会在实际的程序中使用这种方法。因此,
Larry 利用了这种特性,使之变得有用起来。
foreach(
print “I saw $_”; 读入的是@数组列表到最后才I SAW每行出来.
}
在进行深入讨论前,我们要澄清一些事:这种简写只在特定的情况下有效,默认的情况下不会将一行读入变量$_。仅当while
循环的条件判断部分只包含行输入操作才有效◆。如果在条件判断部分还有别的内容,则上述简写无效。
◆由于for 循环的条件部分和while 的条件部分类似,它也能正常工作。
从<>输入
如果
想写一个Perl 程序,使它具有像cat, sed, awk, sort, grep, lpr, 以及许多别的应用程序类似的功能,则<>将帮上你的大忙。对
于其它方面,<>可能帮不上你什么。使用这种方法来书写程序的一个好处是,可以在程序运行时决定其输入
#!/usr/bin/perl -w
#action like this :
#./perl004.pl cash.sh anydoc ...
while(<>){
chomp;
print "$_\n";
}
调用参数
技术上讲,<>从数组@ARGV 中得到调用参数。这个数组是Perl 中的一个特殊数组,其包含调用参数的列表。换句话说,
这和一般数组没什么两样(除了其名字有些特别:全为大写字母),程序开始运行时,调用参数已被存在@ARGV 之中了◆。
<>操作查看@argv 来决定使用哪些文件。如果表为空,则使用标准输入流;否则,使用其找到的相应文件。也就是说,在
启动程序后,使用<>之前,你还有机会修改@argv 的值。例如,下面程序可以处理3 个指定的文件,无论用户在命令行中
输入了什么其它的文件:
@argv = qw# larry mor curly #; #强制使用这三个文件
while(<>){
chomp;
print “It was $_ that I saw in some stooge-like file!\n”;
}
#!/usr/bin/perl -w
#action like this :
#./perl004.pl cash.sh anydoc ... #that is not appear cash.sh anydoc..
@ARGV=qw#iptable.log A.TXT #;# force use the file in the list anyways as input
while(<>){
chomp;
print "$_\n";
输出到标准输出设备
当然,打印数组和内插一个数组是不同的:
print @array; #打印出元素的列表
print “@array”; #打印一个字符串(包含一个内插的数组)
第一个语句打印出所有的元素,一个接着一个,其中没有空格。第二个打印出一个元素,它为@array 的所有元素,其被存
在一个字符串中。也就是说,打印出@array 的所有元素,并由空格分开◆。如果@array 包含qw /fred barney betty /◆,则
第一个例子输出为:fredbarneybetty,而第二个例子输出为fred barney betty(由空格分开)
print 注意:
这是由括号是可选的引起的;有时,人会忽略括号属于哪一部分。当没有括号时,print 是一个列表操作,将后面的所有元
素输出来,这通常是你所希望的。当print 后面是一个开括号时,print 为函数调用,它将输出括号中的内容。由于上述代码
中有括号,则它等同于下面的代码:
(print (2+3)) * 4; #oops!
幸运的是,如果打开了警告时(warnings),Perl 会提示你。因此至少在程序的开发和调试阶段,使用–w 或者use warnings,。
上述规则,对于Perl 中所有的列表函数都是有效的,不仅仅是print, 但print 可能是最容易引起人注意的。如果print(或者
别的函数)后面紧接着一个开括号,则要确保闭括号在所有的参数之后。
5.6 句柄
#!/usr/bin/perl -w
$tu=open SEDTEXT,"/home/zgx/sedtest.txt";
if (!$tu)
{
print "cannot openit \n";
}
while (
{
chomp;
print "$_\n";
}
close SEDTEXT;
while(
foreach(
print $_;
的区别:
while(
什么是哈希?,索引(这里,我们将它叫key)不是数字而是任意的唯一的字符串
keys 和values 均为任意的标量,但keys 通常转换为字符串。因此,如果将表达式50/20 作为keys◆,则其通常被转换为3
字符的字符串“2.5”。这是上图中的一个key。
keys 是唯一的,但values 可以重复。hash 的value 可以是数字,字符串,undef,或者它们的混合◆,但key 是唯一的。
哈希元素的存取
作为整体的hash
要引用整个hash,使用百分号(“%”)作为前缀。前面几页中使用的hash 的名字为%family_name。
为了方便,hash 可以转换为列表,或者反过来。给hash 赋值(本例中,参见图6-1)其类型属于列表context 赋值,其中列
表是key/value 对◆:
◆虽然可以使用任何列表表达式,但其元素个数必须是偶数,因为由key/value 对组成。元素个数为奇数是不可靠的,这通常会引起警告。
%some_hash = (“foo”, 35, “bar”, 12.4, 2.5, “hello”, “wilma”, 1.72e30, “betty”, “bye\n”);
hash 的值(在列表context 中)是一个key/value 对的列表:
@array_array = %some_hash;
我们把这称为:将hash 展开,并将其key/value 对返回到一个列表中。返回的key/value 顺序和存放的顺序可能不同:
print ”;
****Hash 赋值
%new_hash = %old_hash; ---cp
%inverse_hash = reverse %any_hash; key->value; value-->key
大箭头符号(=>)
当给hash 赋值时,有时并不明显哪些元素是keys,那些是values。例如,在下面的赋值中(我们在前面已经见过了),我
们需要仔细的计数,“key,value,key,value,…”,来判断2.5 是key 还是vlaue:
%some_hash = ( “foo”, 35, “bar”, 12.4 ,2.5, “hello”, “Wilma”, 1.72e30, “betty”, “bye\n”);