24学时搞定Perl 读书笔记(二)

24学时搞定Perl 读书笔记(二),第1张

概述第9学时 其他函数与运算符 index函数: index string, substring; index string, substring, start_position; index函数从string的左边开始运行,并搜索substring。index返回找到substring时所在的位置,0是指最左边的字符。 如果没有找到substring,index便返回-1。substring不是一个

第9学时 其他函数与运算符

index函数:
index string,substring;
index string,substring,start_position;
index函数从string的左边开始运行,并搜索substring。index返回找到substring时所在的位置,0是指最左边的字符。
如果没有找到substring,index便返回-1。substring不是一个正则表达式,它只是另一个标量。

rindex函数:
作用与index基本相同,但它是从右向左进行搜索:
rindex string,substring;
rindex string,start_position;
当搜索到结尾时,rindex返回-1。


substr函数:
substr string,offset;
substr string,offset,length;
substr函数取出string,从位置offset开始运行,并返回从offset到结尾的字符串的剩余部分;
如果设定了length,那么取出length指明的字符,或者直到找出字符串的结尾,以先到者为准;
如果offset设定为负值,substr函数将从右边开始计数,例如,substr($a,-5)返回$a的最后5个字符;
如果length设定为负值,则substr返回从它的起点到字符串结尾去掉length长度的字符。

substr函数也可以放在赋值表达式的左边。此时,substr用于指明标量中的什么字符将被替换:
$a="countrymen,lend me your wallets";
#Replace the first character of $a with "Romans"
substr($a,1)="Romans";
#Replace the last 7 characters
substr($a,-7,7)="ears";

转换 *** 作符tr:
tr/searchList/replacementList/;
转换 *** 作符tr///用于搜索一个字符串,找出searchList中的各个元素,并用replacementList中的对应元素对它们进行替换。
按照默认设置,转换 *** 作符用于对变量$_进行搜索和修改。若要搜索和修改其他变量,要使用连接运算符=~,如下所示:
tr /ABC/XYZ/;  #In $_,replace all A's with X's,all B's with Y's,all C's with Z's
$r=~/ABC/XYZ/; #Does the same,but with $r.
如果replacementList是空的,或者与searchList相同,那么tr///将计算并返回匹配的字符。目标字符串并不被修改

最后要说明的是,由于历史的原因,tr///也可以写成y///,其结果相同,因为y与tr同义。
tr///运算符(和y///)也允许你为searchList和replacementList设定另一组界限符。这些界限符可以是任何一组自然配对的字符,
如括号或任何其他字符:tr(a-z)(A-Z);

printf函数:
从C编程语言那里借用的(几乎是原原本本的借用),句法如下:
printf formatList,List
printf filehandle formatstring,List
请注意,filehandle名与formatstring之间不使用逗号。
%表示这是一个域说明符的开始。域说明符的格式是% -w.dx,
其中w是域需要的总宽度,d是小数点左边的位数(对于数字来说)和字符串域允许的总宽度,x表示输出的是数据类型。
x说明符前面加连字符表示该域在w字符中左对齐,否则它进行右对齐。只有%和x是不可少的。

sprintf函数:
与printf几乎相同,不过它不是输出值,而是输出sprintf返回的格式化输出,可以将它赋予一个标量或另一个表达式,如下:
$moonweight=sprintf("%.2f",$weight*.12);
print $moonweight;

push函数和pop函数:
Perl中的堆栈通常用数组来实现。push函压栈;pop函数d出。

shift函数和unshift函数:
从底部修改堆栈。unshift函数用于将元素添加到堆栈的底部,shift函数用于从底部取出元素(即删除)。

以上函数句法如下:
pop target_array;
shift target_array;
push target_array,new_List;
unshift target_array,new_List;

pop与shift函数分别从target_array中删除一个元素。如果target_array没有设定,那么元素可以从@_中删除,也可以从@ARGV中删除。
pop和shift函数返回被删除的元素,如果数组是空的,则返回undef。
在子例程中,如果没有设定其他数组,那么pop、shift、unshift和push函数将修改@_。
在子例程外面的程序主体中,如果没有设定其他数组,那么这些函数将修改数组@ARGV。

当将元素添加给数组时,将元素push(或unshift)到数组中要比手工将元素添加到数组的结尾处更加有效,如:
push(@List,@newitems) 比 @List=(@List,@newitems) 更加有效。
Perl的push、shift、unshift和pup函数都进行了优化,以适应这些 *** 作的需要。

堆栈的“底部”是元素0,堆栈的“顶部”是数组中的最后一个元素。

splice函数:
splice array,offset;
splice array,length;
splice array,length,List;
用于删除数组中从offset位置开始的元素,同时返回被删除的数组元素。
如果offset的值是负值,则从数组的结尾处开始计数;
如果设定了length,那么只删除length指定的元素;
如果设定了List,则删除length指定的元素,并用List的元素取代之.

第10课时 文件与目录

opendir函数:
opendir dirhandle,directory
用于打开目录句柄,dirhandle是要打开的目录句柄,directory是要读取的目录的名字。要是目
录句柄不能打开,你就无权读取该目录的内容,或者该目录根本不存在。opendir函数将返回假。

readdir函数:
目录句柄打开后,可以使用readdir函数来读取它的内容:
readdir dirhandle;
在标量上下文中,readdir函数返回目录中的下一项,如果目录中没有剩下任何项目,则返回undef。
在列表上下文中,readdir返回所有的(剩余的)目录项。
readdir返回的名字包括文件、目录的名字。

closedir函数:
closedir dirhandle;

下面这个例子说明如何读取一个目录,在大多数时候,你对.和..文件是不感兴趣的。若要读取文件句柄并清除这些文件,可以:
opendir(TEMP,'/temp') || dIE "Can not open $!/n";
@fileS = grep(!/^/./.?$/,readdir TEMP);
closedir(TEMP);

若要获得带有特定扩展名的全部文件,可以使用下面的代码:
@fileS = grep(/.txt$/,readdir TEMP);

glob *** 作符:
读取目录中的文件名时使用的另一种方法称为globbing, *** 作符glob的句法是:
glob pattern;
这里的pattern是你要匹配的文件名模式。
在列表上下文中,glob返回与模式匹配的所有文件(和目录);
在标量上下文中,每查询一次glob,便返回一个文件。

表10-1 globbing的模式
字符匹配的模式   举例
?单个字符   f?d用于匹配fud、fID和fdd等。
*任何数目的字符  f*d用于匹配fd、fdd、food和filled等
[chars] 用于匹配任何一个chars  f[ou]d用于匹配fod和fud,但不能匹配fad,MacPerl不支持这个特性
{a,b,...} 既可以匹配字符串a, f* {txt,doc}用于匹配以f开头并且以.txt或.doc结尾的文件,也可以匹配字符串b,MacPerl不支持此特性

下面请看几个globbing的例子:
my @hfiles=glob('/usr/include/*.h');
my @curfiles=glob('*2007*,{txt,doc}');
$count=1;
while($name=glob('*'))
{
 print "$count,$name";
 $count++;
}

chdir函数:
用于改变当前目录。
chdir newdir;
chdir函数将当前工作目录改为newdir。如果newdir目录不存在,或者你不拥有对newdir的访问权,那么chdir返回假。

cwd函数:
若要确定当前目录,必须同时使用两个语句。在程序的某个位置,最好是在靠近程序开始的地方,必须使用语句use Cwd,
然后,当你想要检查当前目录时,使用cwd函数:
use Cwd;
print "Your current directory is :",cwd,"/n";
语句use Cwd实际上让Perl加载一个称为Cwd的模块,使Perl语言增加一些新的函数,如Cwd。

mkdir函数:
创建一个新目录,句法如下:
mkdir newdir,permission;
如果目录newdir能够创建,那么mkdir函数返回真;否则,它返回假,并且将$!设置为mkdir运行失败的原因。

rmdir函数:
删除目录,句法如下:
rmdir pathname;
如果目录pathname可以删除,rmdir函数返回真;如果Pathname无法删除,rmdir返回假,并将$!设置为rmdir运行失败的原因.
rmdir函数只删除完全是空的目录。

unlink函数:
从目录中删除文件,句法如下:
unlink List_of_files;
unlink函数能删除List_of_files中的所有文件,并返回已经删除的文件数量。如果List_of_files被省略,$_中指定的文件将被删除。

rename函数:
给文件或目录改名,句法如下:
rename oldname,newname;
rename函数取出名字为oldname的文件,将它的名字改为newname。如果改名成功,该函数返回真。
如果oldname和newname是目录,那么这些目录将被改名;如果改名不成功,rename返回假,并将$!设置为不成功的原因.

stat函数:
详细而全面地给出关于一个文件的信息。stat函数源于UNIX系统,它的返回值在UNIX系统中与非UNIX系统中略有不同,句法如下:
stat filehandle;
stat filename;
在任何 *** 作系统下,stat均可返回一个包含13个元素的列表,来描述文件的属性。列表中的实际值随着运行的 *** 作系统的不同而有所差异,
因为有些 *** 作系统包含的特性是其他 *** 作系统所没有的。

表10-3 stat函数的返回值
编号 名字  UNIX系统   @R_301_5087@系统
0 dev  设备号    驱动器号(C:通常是2,D:通常是3,等等)
1 ino  索引节号   总是0
2  mode   文件的方式   无
3  nlink  链接号    通常为0;@R_301_5087@ NT;文件系统允许链接
4 uID  文件所有者的用户ID(UID)  总是0
5  gID  文件所有者的组ID (GID)  总是0
6  rdev   特殊文件信息   驱动器号(重复)
7  size   文件大小(以字节计)   文件大小(以字节计)
8 atime  上次访问的时间   上次访问的时间
9 mtime  上次修改的时间上  次修改的时间
10 ctime  Inode修改时间   文件的创建时间
11  blksz  磁盘块的大小   总是0
12 blocks   文件中的块的数量  总是0

有时你可能想从stat返回的列表中仅仅检索1个值。若是这样,可以用括号将整个stat函数括起来,并使用下标将你想要的值标出来:
print "This file has ",(stat("$file"))[7],"bytes of data";

第11课时 系统之间的互 *** 作性

system函数:
system()函数能够暂停Perl程序的运行,然后运行外部命令,接着再运行你的Perl程序,句法如下:
system command;
如果一切正常,系统的返回值是0;否则返回非零值。

system函数有一个不足:
它没有提供特别好的方法,来捕获命令的输出,并将它送往Perl进行分析。如果以迂回方式进行这项 *** 作,可以这样:
system "dir > outfile.txt";
open (FH,"outfile.txt");
@out=<"outfile.txt">;
close(FH);

反引号及其返回值:
Perl有一个方法处理这个问题,即反引号。用反引号(` `)括起来的任何命令均由Perl作为外部命令来运行,就像通过system运行的
一样,其输出被捕获,并且作为反引号的返回值返回:
$directory=`dir`;
在反引号中,可以看到所有标准的shell处理方式: > 负责重定向, | 负责管道传输。在UNIX下,&负责启动后台任务。
不过,在后台运行的命令,以及用>重定向其输出的命令,均没有输出可以捕获。

qx{ }表示法:
qx{ }表示法能起到和反引号一样的作用。通过使用花括号,当反引号作为命令的组成部分时,可不必在反引号的前面加反斜杠,如下所示:
$complex=`sort /`grep -l 'conf' */``; = $complex=qx{sort `grep -l 'conf' *`};
任何字符均可用来取代{},成对的字符如<>,()和[]等均可以使用。

想让Perl进行内插替换的变量前面加上一个反斜杠,如:
$myhome=`ls /$HOME`;
或者
$@R_301_5087@=`dir /%windir%`;
现在,$HOME是UNIX shell的HOME变量,%winddir%是command .com的winddir变量。

请看下面的一组命令:
dir > outfile.txt;
sort outfile.txt > newfile.txt;
more newfile.txt;
dir的输出在outfile中集中,然后使用sort对outfile排序,同时sort的输出被存放在newfile中。
接着more命令显示newfile的内容,每次显示一屏内容。
管道允许你执行与上面相同的命令序列,但是不带outfile和newfile,如下所示:
dir | sort | more;
dir的输出被赋予sort,然后sort对数据进行排序。sort的输出被赋予more,每次显示1页。它不需要重定向(>)或临时文件。

Perl程序可以用不同方式纳入管道。首先,你可以编写一个Perl程序,以便接收输入,对输入进行转换,然后插入管道,如:
dir /B | sort | perl totaler | more
在上面这个管道中, Totaler可以是你编写的Perl程序,以便输出目录列表的合计,也可能是某些统计数字,同时输出目录列表本身

open函数与管道:
Perl参与管道运行的另一种方法是将管道视为既可以读取也可以写入的文件。这是使用Perl中的open函数来实现的,如下所示:
open(RHANDLE,"dir /B | sort |");
在上面这个代码段中,open函数打开一个管道,以便从dir/B | sort中读取数据。当open函数运行时,Perl启动执行dir /B | sort命令。
当文件句柄RHANDLE被读取时,sort的输出被读入Perl程序。
open(WHANDLE,"| more");
这个open函数打开一个管道,以便将数据写入more命令。输出到WHANDLE文件句柄的所有数据均被more缓存,并每次显示1页。
当你完成对已向程序打开的文件句柄(如RHANDLE和WHANDLE)的 *** 作时,应该正确地关闭句柄:
close(WHANDLE) || warn "Pipe to more Failed. $!";

有一个特殊变量$^O,即美元符号、插入记号^和大写字母O,这个变量包含了程序运行时所在的 *** 作系统结构。
例如,在@R_301_5087@和DOS下,它包含字符串MSWin32。在UNIX下,它包含了运行的UNIX类型,如linux,aix和solaris等。


第13课时 引用和结构

若要创建对某个既定变量的引用,可以在该变量的前面加上一个反斜杠。如:
$ref=/$a;
若要通过$ref获得$a中的值,必须间接引用$ref(直接用会得到一个地址值),如:
print $$ref;

也可以创建对数组和哈希结构的引用。可以像创建对标量的引用那样,使用反斜杠来创建对数组和哈希结构的引用:
$aref=/@arr;
若要使用引用$aref来访问@arr的各个部分,可以:
$$aref[0]  @arr的第一个元素
@$aref[2,3]  @arr的一个片
@$aref   @arr的整个数组
使用花括号可以看的更加清楚:
$$aref[0]  与${$aref}[0]相同
$$aref[2,3]  与${$aref}[2,3]相同
@$aref   与@{$aref}相同

若要创建对哈希结构的引用,可以使用反斜杠,就像创建标量和数组的引用那样:
$href=/%hash;
若要使用对哈希的引用%href来访问%hash的各个部分,可以:
$$href{key} 访问%hash中的一个关键字,也可以是${$href}{key}
%$href  访问整个哈希结构,也可以是%{$href}
若要迭代通过该哈希结构,输出所有的值,可以:
foreach $key (keys $$key)
{ print "$$href{key}/n"; }

引用存在的目的之一:
当一个参数需要两个数组作为参数的时候,就必须使用两个数组的引用来作为参数了,否则传过去的时候相当于一个大数组:
@fruit=qw(apple orange pear);
@vegetable=qw(carrot cabbage);
getarrays(/@fruit,/@vegetable);
sub getarrays
{
  my($refFruit,$refvegetable)=@_;
  ...
}

只要对哈希结构或数组的引用存在,即使原始数据不再存在,Perl仍然保留着哈希结构和数组的各个元素:
my $href;
{
 my %hash=(phone=>"Finix",light=>"Lei");
 $href=/%hash;
}
print $$href{phone};  #right,it will print 'Finix'
在这个代码块中,标量$href被赋予对%hash的引用。当该代码块存在时,即使%hash已经消失,$href中的引用仍然有效
(因为%hash是代码块的专用结构)。当结构本身已经超出作用域之后,对该结构的引用仍然存在, $href引用的哈希结构仍然可以修改。

匿名引用:
使用方括号或花括号来表示匿名引用:
Perl提供了一个机制,可以用来创建引用,而不必使用中间的哈希结构%hash。这个机制称为匿名存储。
下面创建了一个对匿名哈希结构的引用,并把它存储在$aref中:
$aref={phone=>"Finix",light=>"Lei"};
花括号{ }将哈希结构括起来,返回对它的引用,但实际上并没有创建新的变量,也可以使用方括号:
$refMusic = [ qw{pop classic rock} ];

Perl实际上并不支持真正的二维数组。Perl允许你使用数组引用的数组,模仿建立二维数组:
@List_of_Lists=
(
  [ qw(Finix Lei Hello) ],
  [ qw(World Cpp Java) ],
  [ qw(Good Bad) ]
);
上面的代码段创建了一个正则列表@List_of_Lists,它由对其他列表的引用所组成.若要访问各个元素,可以:
$List_of_Lists[1][2];

若要确定最外层的列表中的元素数目。使用$#表示法或者使用标量上下文中的数组名:
$#List_of_Lists;  #last element of @List_of_Lists:2
scalar(@List_of_Lists); #number of rows in @List_of_Lists:3

若要确定里层列表中的某个列表的元素数目:
scalar(@{$List_of_Lists[1]});

若要遍历列表中的每个元素,可以使用下面这个代码:
foreach my $i (@List_of_Lists)
{
 foreach my $j (@{$i}) #花括号表示没有实际的变量来表示这么一个数组,这里只是一个引用。花括号中的内容就是数组的内容。
 {
  print $j;
 }
}

在Perl中,/($a,$b,$c)实际上是(/$a,/$b,/$c)的简化形式。该表达式的结果实际上是对括号中最后一个元素$c的引用。
若要获得一个对匿名数组的引用,你应该使用:
$ref = [$a,$b,$c];

第14课时 使用模块

若要在你的Perl程序中使用模块,可以使用Perl的use命令。

模块的名字是区分大小写字母的,Cwd和cwd是不一样的。

若要在你的程序中使用file::Find模块,只需将下面这个命令输入到你的程序的顶部:
use file::Find;
这时find函数就可以使用了,句法如下所示:
find subref,dirList;
find函数的第二个参数是要搜索的一个目录列表。第一个参数对你来说是新的,它是个子例程引用。你创建的子例程引用很像是标量或数组的
引用,它只不过是前面加上一个反斜杠的子例程名。必须使用子例程名前面的&,才能取得子例程的引用。然后为dirList中找到的每个文件和
目录调用指明的子例程。
use file::Find;
sub wanted
{
 if($_ eq "important.doc")
 {
  print file::Find::name;
 }
}
find /&wanted,'/documents';

由find调用的函数将可以使用下列变量:
$file::Find::name  当前路径名、目录和文件名。
$file::Find::dir 当前目录名。
$_    当前文件名(不带目录)。

另一个常见 *** 作是拷贝文件:
use file::copy;
copy("sourcefile","destfile") || dIE "Could not copy files. $!";
上面这个代码段用于将sourcefile的内容拷贝到destination。如果拷贝成功,copy函数返回1,如果拷贝出现问题,则返回0

file::copy模块也提供了一个move函数。move函数能够将文件从一个目录移到另一个目录。

可以使用Net::Ping模块来确定你的系统是否能够在网络上正确地进行通信。
Pingecho "www.sohu.com",10;
第二个参数用于指明Pingecho应该等待多长时间才能收到对方的应答,这个时间以秒为单位计算。

第15学时 了解程序的运行性能 (DBM文件)

若要将哈希结构与DBM文件连接起来,可以使用Perl函数dbmopen,如下所示:
dbmopen(hash,filename,mode);
dbmopen函数将hash与一个DBM文件连接起来。你提供的filename实际上在硬盘上创建两
个不同的文件,即filename.pag和filename.dir。Perl使用这两个文件来存储哈希结构。
mode是指对Perl创建的两个DBM文件的访问许可权。

若要使哈希结构与DBM文件断开连接,请像下面这样使用带有哈希结构名字的dbmclose函数:
dbmclose(%hash);

当你将哈希结构与DBM文件连接起来时,必须了解下列要点:
1 关键字和数据的长度现在是受限制的。通常情况下,哈希结构的关键字和数据长度是不
受限制的,与DBM文件相连接的哈希结构拥有一个有限的单个关键字和一个数据,合
起来的长度通常为1024字符左右,这是对DBM文件的一个限制。可以存储的关键字和
值的总数没有变更,它只受文件系统的限制。
2 运行dbmopen以前的哈希结构中的值均被丢失,最好只使用新的哈希结构。

Perl有一个函数,可以允许你对哈希结构进行迭代 *** 作,每次取出一个关键字。这个函数称为each。
each的句法如下:
($key,$val)=each(%hash);
each函数返回由两个元素组成的列表,这两个元素中一个是哈希结构的关键字,另一个是它的值。

对较大的哈希结构进行迭代 *** 作时,更好的方法是使用下面的代码:
dbmopen(%recs,"records",0644) || dIE "Can not open records.$!/n";
while(($key,$val)=each(%hash))
{
 print "$key = $val/n";
}
dbmclose(%recs);
你不一定必须将each函数用于与DBM文件相连接的哈希结构,可以将each用于任何哈希结构。

表15-1 打开文件的不同方式

open命令    读 写 附加 创建? 截断现有数据?
open(F,“<file”)或者open(F,"file”)  是 否 否 否 否
或者open(F,"file”)
open(F,“>file”)    否 是 否 是 是
open(F,“> >file”)    否 是 是 是 否
open(F,“+ <file”)    是 是 否 否 否
open(F,“+ >file”)    是 是 否 是 是
open(F,“+ > >file”)    是 是 是 是 是

若要将指针移到文件中的某个位置,你可以使用seek函数。seek函数带有两个参数。第一
个参数是个打开的文件句柄,第二个参数是文件中你想寻找到的位移。第二个参数是该位移
处于什么位置。0是文件的开始处;1是文件中的当前位置;2是文件的结尾。

若要锁定UNIX和@R_301_5087@ NT下的文件,可以使用Perl的flock函数。flock函数提供了一
个“诱导式”锁定机制。

flock函数带有两个参数,一个是文件句柄,另一个是锁的类型,请看下面的语句:
use Fcntl qw(:flock);
flock(fileHANDLE,lock_type);
如果锁定成功,那么flock函数返回真,否则返回假。有时,调用flock会导致你的程序暂
停运行,以等待其他锁被打开。

文件锁有两种类型,一种是公用锁,一种是专用锁。通常情况下,当想要读取文件时,
可以使用公用锁,而当将数据写入文件时,可以使用专用锁。如果一个进程拥有对文件的专
用锁,那么这是那里存在的唯一的锁,其他进程则根本不拥有锁。但是,只要不存在专用锁,
那么许多进程可以同时拥有公用锁。这是因为只要没有人写入文件,那么许多进程就可以安
全地同时读取文件。

下面是lock_type可以使用的一些值:
Lock_SH 这个值要求在文件上设置公用锁。如果另一个进程拥有该文件的专用锁,那
么flock函数就会暂停运行,直到专用锁被清除,然后再取出该文件的公用锁。
Lock_EX 这个值要求对已经打开而用于写入的文件设置一个专用锁。如果其他进程拥
有一个锁(公用锁或专用锁均可),那么flock就暂停运行,直到这些锁被清除。
Lock_UN 这个值用于释放一个锁。但是,很少需要这样做。你只要关闭文件,就可以
写出所有未写的数据并释放文件锁。如果释放仍然打开的文件上的锁,就会导致数据被
破坏。

需要某种称为信标文件的东西。信标文件是个牺牲性文件,它没
有什么重要的内容,凡是对该文件拥有锁的人,均能处理该文件。
若要使用信标文件,你只需要有一个可以用作信标的文件名和两个函数,用于将信标文
件锁定和解锁。

通用锁函数
use Fcntl qw(:flock);
my $semfile="/tmp/semtmp.sem";
sub get_lock
{
 open(SEM,@semfile) || dIE "Can not open.$!/n";
 flock(SEM,LOCK_EX) || dIE "Lock Failed.$!/n";
}

sub release_lock{ close(SEM);}具体用法:get_lock();#对其他文件的 *** 作,不使用Lock_Typerelease_lock();

总结

以上是内存溢出为你收集整理的24学时搞定Perl 读书笔记(二)全部内容,希望文章能够帮你解决24学时搞定Perl 读书笔记(二)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1288276.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存