Board logo

标题: perl 心得 [打印本页]

作者: 苹果也疯狂    时间: 2014-6-16 13:12     标题: perl 心得

Perl中有一个叫做%ENV的环境变量,和其它的HASH散列一样,它可以被赋值,被打印。



永久赋值的方法:
Windows下:我的电脑->属性->高级->环境变量
Linux/Unix下: export KEY="value"
删除环境变量:unset KEY



或者<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="perl 心得" name=image_operate_59121375863113294 alt="perl 心得" src="http://s7.sinaimg.cn/mw690/735f2910gx6BFuoHMUKa6&690" width=522 height=84 action-type="show-slide" action-data="http%3A%2F%2Fs7.sinaimg.cn%2Fmw690%2F735f2910gx6BFuoHMUKa6%26690" real_src="http://s7.sinaimg.cn/mw690/735f2910gx6BFuoHMUKa6&690">




Ctrl+z可以终止程序!!!!



perl中的钻石操作符


钻石操作符<>是perl的读取文件(文件名通过参数传入,即@ARGV数组。如果@ARGV为空,则改用标准输入流)每一行的操作符,让perl程序也能像cat,sed等应用程序直接处理文本文件。是一个整行输入操作符的特例。


钻石操作符:<>
它能让程序在处理调用参数时,提供类似于标准unix工具程序的用法。若时不提供任何调用参数,程序应该改成出来标准输入流。但有个特例;如果某个参数是连字符(-),那耶代表标准输入。
钻石操作符是整行输入操作符的特例,例如:
while (defined($line = <>) {
chomp ($line);
print "It was $line that I saw! ";
}
既然是整行输入操作符的一种特例,因此可以使用先前我们所看到的简写,将输入读取到默认的$_里:
while (<>) {
chomp;
print "It was $_ that I saw; ";
}
严格来说,钻石操作符并不好真的去检查调用参数,它靠的是@ARGV数组。这个数组是由perl解释器事先建立的特殊数组,其内容就是调用
参数所组成的列表。
钻石操作符如何绝对使用那些文件名?方法如下:它会查找@ARGV,如果它找到的是空列表,就会改用标准输入流;否则,就会使用@ARGV里的文件列表。这表示程序开始运行之后,只要尚未使用钻石操作符,就都可以对@ARGV动点手脚。举例来说,我们可以不管用户在命令行指定了什么,而是一律出来3个特定的文件:
@ARGV = qw / larry moe curly /;
while (<>) {
chomp;
print "It was $_ that I saw in som stooge-like file! ";
}

print <> ;  
cat 的perl实现,

print sort <> ; sort的perl实现

<>的另一个例子,通过打开的文件描述符
open(HANDLE,"c:/test.txt")  
or  
die  
"文件不能打开";  

while  
()  





#注:这就是对文件句柄读取一行并存入变量  
$_   

{   
print;  















#注:打印变量  
$_   

}



以在windows操作系统为例,当我们在命令行中调用PERL程序的时候,我们往往会跟随一些参数,比如输入文件名,和输出文件名之类的信息。这些信息PERL会将它们存储在@ARGV数组中(和C语言一样)。比如在cmd中输入如下命令:
pp.pl -opcamfile opcamfile.ini -rcfile rcfile.txt -swapfile swapfile.tmp -outfile outfile.txt
PERL会建立一个数组@ARGV=qw/-opcamfile opcamfile.ini -rcfile rcfile.txt -swapfile swapfile.tmp -outfile outfile.txt/;然后我们想把这些信息做何用出就对应的处理数组,从数组中分离我们想要的数据就可以了。}




捕获变量:


捕获的功能指的是:把圆括号中模式所匹配的部分字符串暂时记忆下来的能力。如果有一对以上的圆括号。就会有一次以上的捕获。每个被捕获的对象是原本的字符串,而不是模式。
因为捕获标量存储的都是字符串,所以他们都是标量变量。 在Perl中,被捕获的字符串被存储在$1,$2,$3....中。
Perl 的正则表达式中如果出现 () ,则发生匹配或替换后 () 内的模式被 Perl 解释器自动依次赋给系统 $1, $2 ......


下面例子:


$_ = "abc  
def, ghi";

if(/(\S+)  
(\S+), (\S+)/)

{
print "$1 $2 $3\n";
}



解释:
\s
匹配任意的空白字符,如空格、制表符、换行符、中文全角空格等
\S
匹配任意的非空白字符(大写相反)


<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="perl 心得" name=image_operate_92691376032176394 alt="perl 心得" src="http://s1.sinaimg.cn/mw690/735f2910gx6BIBTdBtKb0&690" width=386 height=199 real_src="http://s1.sinaimg.cn/mw690/735f2910gx6BIBTdBtKb0&690">


Perl双引号和单引号的区别:


1)单引号:


它将单引号中的内容包括Perl双引号完整输出,同时即使引号中包含了变量或标量,都将被作为字符处理,如下
$a=5;
print'$a';
结果将输出$a。
仅当后面所跟的字符是反斜杠或单引号时,反斜杠才有意义。
双引号:

双引号:和单引号内的字符串一样,它也是一连串的字符,不过是被括在一对双引号里面。但是现在反斜线具有完整的能力,可用来表示控制字符或通过八进制及十六进制来表示任何字符。如\n, \r,\t等特殊转义。
总结:
一、双中有双,单中有单都需要\ 转义。
二、双中有单或单中有双均不需要转义。
三、单引号直接了当,引号内是什么就显示什么,双引号则需要考虑转义或变量替换等。

特殊运算符:
2**3 表示2的3次方,等于8.(指数运算符)
10%3,10除以3的余数,等于1.取模运算符
字符串拼接运算符:
"hello" . "world"  等同于"helloworld"
字符串重复运算符:,用一个小写字母x来表示
"fred" x 3 就是"fredfredfred"
$a = $a + 5;等同于 $a +=5;
类似的
$str = $str . " "; 等同于 $str .= " ";  
字符串拼接运算符
$a**=3; 表示取$a中的数值的三次方,结果放回$a中。 其他二元复制运算符类似。

列表构造函数
@a = (1..5);  等于  @a = (1,2,3,4,5);
@a = (2..6,10,12); 等于  @a = (2,3,4,5,6,10,12)


@name = qw(fred



barne



betty



wilma



};
等于  
@name = ("fred","barne","betty","wilma");

数组引用用$  

@name 的第一个元素是$name[0]
数组片段用@  

@name 的一个片段:  
@name[1,2]
foreach
Perl foreach从列表(数组)的第一个元素一直循环执行到最后一个元素,一次迭代一个。
@a = (1,2,3,4,5);
foreach $b (reverse @a)
{ print #b;}
输出54321。
当然也可以使用默认变量$_:
@a = (1,2,3,4,5);
foreach  (reverse @a)
{ print;}

哈希
#初始化%h为空数组 %h={};
#用数组初始化%h为a=>1,b=>2
%h=('a',1,'b',2);

哈希元素的存取
要访问hash 元素,可以使用下面的语法:$hash{$some_key}
这和访问数组元素的方法有些类似,这里下标(key)上使用的是花括号({}),而不是方括号([ ])。现在key 的表达式是字符串,而非数字。

.作为整体的hash
要引用整个hash,使用百分号(%)作为前缀。
为了方便,hash可以转换为列表,或者反过来。
Hash 赋值
可以使用如下的语法在hash 之间拷贝:
%new_hash = %old_hash;
将hash转变成其它形式更加常见。例如,我们可以将hash反转:
%inverse_hash = reverse %any_hash;
大箭头符号(=>)
当给hash赋值时,有时并不明显哪些元素是keys,那些是values,因此发明了大箭头符号(=>)。在需要逗号的时候,都可以使用大箭头符号替换。
如:
my %last_name = (
"www" => 1,
"eee" => 2,
);
哈希函数
某些有用的函数可以对整个hash 进行操作。
1.keys和values函数
keys函数会返回此hash的所有keys,values函数将返回所有的values。如果hash中没有元素,则此函数将返回空列表。
my %hash = ("a"=>1, "b"=>2, "c"=>3);
print my @k = keys %hash;
print my @v = values %hash;
2.each函数
如果想迭代hash的每一个元素,一种通常的方法是使用each函数,它将返回key/value对应的2个元素列表。
当对同一个hash 函数进行一次迭代时,将返回下一个key/value对,直到所有的元素均被访问。如果没有更多的key/value对,则each函数将返回空表。
my %hash = ("a"=>1, "b"=>2, "c"=>3);
while(($key, $value) = each %hash)
{




print "$key => $value\n";
}
当然,each返回的key/vlaue对,顺序是混乱的(它其顺序和keys和values函数返回的顺序相同)。如果想将其按序排放,可以对它们排序(使用sort)。
my %hash = ("a"=>1, "b"=>2, "c"=>3, "d"=>4);
foreach $key (sort keys %hash)
{




$value =$hash{$key};




print "$key => $value\n";
}
四、哈希的通常用法
1.exists函数
要查看hash中是否存在某个key,可以使用exists函数,如果hash中存在此key,则返回true,与是否有对应的value无关。
my %hash = ("a"=>1, "b"=>2, "c"=>3, "d"=>4);
if(exists $hash{'a'})
{




print "true";
}
2.delete 函数
delete函数将某个给定的key(包括其对应的value)从hash中删除。如果不存在这个key,则什么也不做,不会有警告或者错误信息。
my %hash = ("a"=>1, "b"=>2, "c"=>3, "d"=>4);
delete $hash{'a'};
foreach $key (sort keys %hash)
{




$value =$hash{$key};




print "$key => $value\n";
}
3.hash 元素的内插
你可以在双引号的字符串中使用单个hash元素,但不支持整个hash 的内插。
my %hash = ("a"=>1, "b"=>2, "c"=>3, "d"=>4);
foreach $key (sort keys %hash)
{




print "$key => $hash{$key}\n";
}

哈希表片段:
比如一个桌球俱乐部有10个人,每个人有一个分数。做成一个哈希表%score。想要对其中三个人的分数赋值:
$score{"fred"} = 123;
$score{"barney"} = 446;
$score{"dino"} = 789;
这样有点啰嗦。
可以写成:
{ $score{"fred"},$score{"barney"},$score{"dino"} } = (123,446,789);
更简单的是:
@score{"fred","barney","dino"} = (123,446,789);

子程序
在Perl 中,会自动将此参数列表(此参数列表的另一个名字)自动存放在一个叫做@_的数组中。子程序可以访问此数组变量来确定此参数的个数以及其值。
这也就是说此子程序参数的第一个值存放在$_[0]中,第二个存放在$_[1],依次类推。但必须强调的是这些变量和$_这个
变量没有任何关系。







@_是子程序的一个私有变量;


sub add{$_[0] + $_[1]};
print add(3,4);
返回7
注意子程序定义的后面用的是{ } 而不是(),否则会出现malformed prototype for main。。。之类的报错
调用子程序时使用()括住参数。
say("me")+say("you");




sub say  {print "hello, $_[0]!\n";}

显示:

hello, me!

hello, you!






返回值
任何perl子程序都有返回值,子程序的返回值是return语句的值或是子程序中最后一个表达式的值。
sub sum_of_and_barney{
print “hey,you called the sum_of_fred_and_barney subroutine!/n”
$fred+$barney; #这就是返回值
}
如果最后语句为print语句,它的返回值通常是1,代表“输出成功”
参数
Perl子程序可以有参数,要传递参数列表到子程序中,只要在子程序调用的后面加上被括号圈引的列表表达式即可。
$n=&max(10,15); #包含两个参数子程序调用
参数列表将会被传入子程序,让子程序随意使用。Perl自动将列表化为特殊的数组变量@_,该变量在子程序执行期间有效,子程序可以访问这个数组。
子程序中的私有变量
默认情况下,Perl中所有的变量都是全局变量,可用随时运用操作符my来创建私有的词法变量:
sub max{
my ($m,$n); #该语句中的新的私有变量
 ($m,$n)=@_;
If ($m>$n) {$m} else {$n}
}
长度可变的参数列表
Perl子程序可以很容易地通过检查@_数组的长度来确定参数的个数
更好的&max子程序
$maximum=&max(3,5,10,4,6);

sub max{
my($max_so_far)=shift @_; #数组中的第一个值,暂时把它当成最大值
 foreach (@_) { #遍历数组@_中的其他元素
if ($_> $max_so_far){   #当前元素比$max_so_far更大吗?
$max_so_far=$_;
}
}
$max_so_far;
}


perl控制结构:

指令: if 假如
语法一:
if(判别运算式)
{
表达式为真时的语句块;

}
上个语法在Perl中也可以写成:
表达式为真时的语句块 if (判别运算式);
范例:
print"请输入您的分数?\n";
$scorre=; #代表标准输入,会让使用者输入一字符串
chop($score); #将$score最后一个换行字符\n删除掉
if($score>=60){

print"您的分数及格了!\n";

}
也可以写成: print "您的分数及格了!\n" if ($score>=60);
语法二:
if(判别运算式一){

判别式一为真时的语句块;

}else{

判别式一为假时的语句块;

}

语法三:
if (判别运算式一)
{

判别式一为真时的语句块;

}elsif(判别运算式二){

判别式二为真时的语句块;

}elsif(判别运算式三){

判别式三为真时的语句块;

}else{

所有判别式为假时的语句块;

}


指令: unless 假如非
unless的含义就是说“如果判别式不为真,就执行...”。与if正好相反
语法一:
unless(判别运算式) {

判别式为假时语句块;

}
上个语法在Perl中也可以写成:判别式为假时语句块 unless (判别运算式);


进阶技巧:&&,||及?:作为控制结构
它们看上去像标点符号,或是表达式的一部分。但在Perl中可作为控制结构。
比如说:
 if (判别表达式)
  {为真时语句块};
也可以写为:
 为真时的语句块 if (判别表达式)
但更简单的方式是:
 判别式 && 为真时的语句块
为什么呢?&&为逻辑与操作符,其含义为:
  若判别式为真,则表达式的值依赖于后面语句块的值。所以为真时的语句块被执行(用来求值)。
  若判别式为假,则整个表达式为假,不用考虑后面语句块的值。所以为假时的语句块不被执行。
同样道理,
unless(this){that}可替换为this||that
?:表达式举例:exp1?exp2:exp3表示:如果exp1为真则求exp2的值,否则求exp3的值。



while(判别运算式)
{

程序叙述区块;

}
程序叙述区块 while (判别运算式);
until(判别运算式)
{

程序叙述区块;

}
程序叙述区块 until (判别运算式);


在while和do while循环中最大的不同是在do while循环中,程序叙述区块至少会被执行一次。



do while 当..

语法:
do
{

程序叙述区块;

}while(判别运算式);


do until 直到...才
do{

程序叙述区块;

}until (判别运算式);
范例:
print ("This is zero.\n") if ($var == 0);

  print ("This is zero.\n") unless ($var != 0);

  print ("Not zero yet.\n") while ($var-- > 0);

  print ("Not zero yet.\n") until ($var-- == 0);



last语句能够使当前正在运行的最里面的循环块退出。它类似c语言中的break。
next控制流允许你跳到当前循环的末尾, 开始下一次循环。它类似c语言中的continue。
redo会跳到当前循环块的顶端,不进行条件表达式判断以及接着本次循环。next和redo的最大区别在于,next 会进入下一次循环,而redo 会继续执行本次循环。
如果要从最内层的循环中跳出来,可以使用标签(label),推荐标签均大写

.last

last
会立刻结束循环。(这同C 语言或其它语言中的“break”语句类似)。

while(){






if(/stop/){






  





last;






  

}elsif(/fred/){






  





print;


  


}






}

##last跳转到这里##



next

next
之后,又会进入下一轮循环(这和C 或者类似语言的“continue”相似)


my @words = qw{ fredbarney pebbles dinoWilma betty };

my $errors = 0;

foreach (@words)

{

  
##redo 跳到这里##

  
print "Type the word $_: ";

  
chomp(my $try = );

  
if($try ne $_){

  


print "sorry ?That’s not right.\n\n";

  


$errors++;

  


next;

  
}

  
print "This word is right.\n\n";


#跳转到这里

}

print "You’ve completed the test, with $errors error\n";


redo

循环控制的第三个操作是redo。它会调到当前循环块的顶端,不进行条件表达式判断以及接着本次循环。(在C 或类似语言中没有这种操作。)



my $errors = 0;
foreach (@words)
{
  
##redo 跳到这里##

  
print "Type the word $_: ";

  
chomp(my $try = );

  
if($try ne $_){

  


print "sorry ?That’s not right.\n\n";

  


$errors++;

  


redo; #跳转到循环顶端

  
}

}
print "You’ve completed the test, with $errors error\n";


字符串操作函数:

1、$position = index($string,$substring,$skipchars);
   
该函数返回子串substring在字符串string中的位置,如果不存在,则返回-1;参数skipchars是可选参数,表示查找之前跳过的字符数,即:从该位置处开始查找;

2、rindex($string,$substring,$skipchars):功能与index()类似,不同的是它从string的右端开始查找;
3、$Len = length($string):求字符串的长度;
4 、 $offset = pos(string):返回最后一次模式匹配的位置;
5、$substring = substr($string,$skipchars,$length):该函数在字符串string中跳过skipchars个字符的位置(从skipchars位置处)开始抽取长度为length的子串;第一个字符的位置为0;
6、lc($string):把string中的所有字母都转换成小写字母;
7、uc($string):把string中的所有字母都转换成大写字母;
8、lcfirst($string):把string中的第一个字母转换成小写字母;
9、ucfirst($string):把string中的第一个字母转换成大写字母;
12、sprintf(formatstring,field1,field2,。。。,fieldn):该函数的功能同C语言中的sprintf()函数;都是多字符串进行格式化,不同的是该函数返回格式化后的结果字符串;

$result = sprintf("d",$number);让$number有8个前导零。
$rounded = sprintf("%.3f",$number); 让小数点后有3位数字。
13、hex($string):把字符串形式的十六进制数据转换成十进制的整数;
14、int($floatnum):把浮点数去掉小数部分而转换成整数;
15、oct($ocunum):把字符串形式的八进制(0)或十六进制(0x)数据转换成十进制数;
18、defined($expr):判断一个变量、数组或数组中的一个元素是否已经被赋值;expr为一个变量名、数组名或一个数组元素;如果已经定义或赋值,则返回true,否则返回false;
$s1 . $s2 将 $s2连接在 $s1的末尾并返回。
$s1 x 2  将 $s1重复两遍并返回
$s1  .= $s2 将 $s2添加到 $s1的末尾。

输出当前时间

$t = time();

$now = localtime($t);

print "Time is: $now\n";

grep函数
@list = (tomatoes, tomorrow, potatoes, phantom, Tommy);
$count = grep( /tom/i, @list);
@items= grep( /tom/i, @list);
print "Found items: @items\nNumber found: $count\n";

/i表示关闭大小写敏感,$count返回4

<IMG style="PADDING-BOTTOM: 0px; BORDER-RIGHT-WIDTH: 0px; LIST-STYLE-TYPE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; PADDING-TOP: 0px; border-image: initial" title="perl 心得" name=image_operate_32781388818440799 alt="perl 心得" src="http://s11.sinaimg.cn/mw690/0026ZEdigy6FwEEtXESea&690" width=363 height=40 real_src="http://s11.sinaimg.cn/mw690/0026ZEdigy6FwEEtXESea&690">



map函数

Perl map BLOCKLIST
Perl map EXPR,LIST
BLOCK是一个用{}包围的代码块。EXPR可以是子函数名、正则表达式等。LIST是输入列表。

简单地说,Perl map函数就是起了一个替代foreach循环的作用,Perl map函数会把数组LIST中的元素挨个取出,放到系统变量$_中,然后调用BLOCK去处理。

现在取出书名里面所有用到的单词,并且全部转换成大写
my @books = ( 'Pride and Prejudice', 'Emma', 'Masfield Park', 'Sense and Sensibility', 'Nothanger Abbey', 'Persuasion', 'Lady Susan', 'Sanditon', 'The Watsons');
my @words = map
{split( //s+/, $_)}
@books;  

  split( //s+/, $_)是代码块
my @uppercases = map uc, @words;

splice函数
1 在数组中用其他元素代替数组部分元素,用法为splice(@list,offset,length,@new),即把@new中的元素替换数组@list中从offset位置开始且长度为length的元素。
2 从数组中删除元素,用法为splice(@list,offset,length),即把数组@list中从offset开始长度为length的元素去掉。
3 清空数组,用法为splice(@list)。此外,undef(@list)也可以清空数组。
例如:
   @d=(1..9);
   my @e=("a".."f");
   splice(@d,2,2,@e); #目标数组, 插入起始位置, 覆盖长度, 插入数组

将会得到12abcdef56789
splice的第二个功能是删除,例如在刚才的代码上面再加上:
   splice(@d,2,3); #目标数组, 起始位置,删除长度
将可以得到126789;
splice的第三个功能就是删除到末尾。语法为:
   splice(@d,2);
就是从第二个开始,删除到末尾。





指令:substr
语法:substr($string,offset,length)
offset代表起始字符的位置,length代表引用的字符串长度,如果省略length则代表从起始值到字符串的最后一个字符长度。而offset如果是负值的话,就会从字符串右边开始指定字符。

$temp = substr("okay", 2);
print "Substring valuye is $temp\n";
$temp = substr("okay", 1,2);
print "Substring valuye is $temp\n";
这将产生以下结果:

Substring valuye is ay
Substring valuye is ka







欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0