Perl5学习笔记-第五章-文件读写
一、打开、关闭文件
二、读文件
三、写文件
四、判断文件状态
五、命令行参数
六、打开管道
七、相关的文件、目录操作函数
处理文件的基本原理很简单:你关联与外部实体(通常是文件)的文件句柄,然后使用各种在Perl的运算符和函数内与句柄相关联的数据流中存储的数据读取和更新。一个句柄是一个名为Perl的内部结构,关联物理文件名称。所有的文件句柄是读/写访问,所以你可以读取和更新与句柄相关联的任何文件或设备的能力。然而,当你关联的文件句柄,你可以在被打开的文件句柄指定的模式。
三个基本文件的句柄是:STDIN, STDOUT 和 STDERR.
一、打开、关闭文件
语法为:open(filevar, filename),其中filevar为文件句柄,或者说是程序中用来代表某文件的代号,filename为文件名,其路径可为相对路径,亦可为绝对路径。
open(FILE1,"file1");
open(FILE1, "/u/jqpublic/file1");
打开文件时必须决定访问模式,在Perl中有三种访问模式:读、写和添加。后两种模式的区别在于写模式将原文件覆盖,原有内容丢失,形式为:open (outfile,">outfile");而添加模式则在原文件的末尾处继续添加内容,形式为:open(appendfile, ">>appendfile")。要注意的是:不能对文件同时进行读和写/添加操作。
open的返回值用来确定打开文件的操作是否成功,当其成功时返回非零值,失败时返回零,因此可以如下判断:
if (open(MYFILE, "myfile")) {
# here's what to do if the file opened successfully
}
当文件打开失败时结束程序:
unless (open (MYFILE, "file1")) {
die ("cannot open input file file1\n");
}
亦可用逻辑或操作符表示如下:
open (MYFILE, "file1") || die ("Could not open file");
当文件操作完毕后,用close(MYFILE); 关闭文件。
Per有以下两个函数以及多形式可以用来打开任何新的或现有的文件。
open FILEHANDLE, EXPR
open FILEHANDLE
sysopen FILEHANDLE, FILENAME, MODE, PERMS
sysopen FILEHANDLE, FILENAME, MODE
参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
EXPR:文件名及文件访问类型组成的表达式。
MODE:文件访问类型。
PERMS:访问权限位(permission bits)。
这里的FILEHANDLE是由open函数返回的文件句柄和expr是打开文件的文件名和模式的表达式。以下是语法在只读模式打开file.txt的。下面表明该文件是只读模式打开:
open(DATA, "<file.txt");
二、读文件
语句$line =<>;从文件中读取一行数据存储到简单变量$line中并把文件指针向后移动一行。为标准输入文件,通常为键盘输入,不需要打开。语句@array = <>;把文件的全部内容读入数组@array,文件的每一行(含回车符)为@array的一个元素。
perl中使用一对尖括号格式的<STDIN>来读取来自非文件的标准输入,例如来自管道的数据,来自输入重定向的数据或者来自键盘的输入。需要注意的是,<STDIN>读取的输入会自带换行符,所以print输出的时候不要加上额外的换行符。
三、写文件
形式为:
open(OUTFILE, ">outfile");
print OUTFILE ("Here is an output line.\n");
注:STDOUT、STDERR为标准输出和标准错误文件,通常为屏幕,且不需要打开。
四、判断文件状态
1、文件测试操作符
语法为:-op expr,如:
if (-e "/path/file1") {
print STDERR ("File file1 exists.\n");
}
文件测试操作符
操作符 描述
-b 是否为块设备
-c 是否为字符设备
-d 是否为目录
-e 是否存在
-f 是否为普通文件
-g 是否设置了setgid位
-k 是否设置了sticky位
-l 是否为符号链接
-o 是否拥有该文件
-p 是否为管道
-r 是否可读
-s 是否非空
-t 是否表示终端
-u 是否设置了setuid位
-w 是否可写
-x 是否可执行
-z 是否为空文件
-A 距上次访问多长时间
-B 是否为二进制文件
-C 距上次访问文件的inode多长时间
-M 距上次修改多长时间
-O 是否只为“真正的用户”所拥有
-R 是否只有“真正的用户”可读
-S 是否为socket
-T 是否为文本文件
-W 是否只有"真正的用户"可写
-X 是否只有"真正的用户"可执行
注:“真正的用户”指登录时指定的userid,与当前进程用户ID相对,命令suid可以改变有效用户ID。例:
unless (open(INFILE, "infile")) {
die ("Input file infile cannot be opened.\n");
}
if (-e "outfile") {
die ("Output file outfile already exists.\n");
}
unless (open(OUTFILE, ">outfile")) {
die ("Output file outfile cannot be opened.\n");
}
等价于
open(INFILE, "infile") && !(-e "outfile") &&
open(OUTFILE, ">outfile") || die("Cannot open files\n");
五、命令行参数的解释
象C一样,Perl也有存储命令行参数的数组@ARGV,可以用来分别处理各个命令行参数;与C不同的是,$ARGV[0]是第一个参数,而不是程序名本身。
$var = $ARGV[0]; # 第一个参数
$numargs = @ARGV; # 参数的个数
Perl中,操作符实际上是对数组@ARGV的隐含的引用,其工作原理为:
1、当Perl解释器第一次看到时,打开以$ARGV[0]为文件名的文件;
2、执行动作shift(@ARGV); 即把数组@ARGV的元素向前移动一个,其元素数量即减少了一个。
3、操作符读取在第一步打开的文件中的所有行。
4、读完后,解释器回到第一步重复。
@ARGV = ("myfile1", "myfile2"); #实际上由命令行参数赋值
while ($line = <>) {
print ($line);
}
将把文件myfile1和myfile2的内容打印出来。
函数的参数
&abc("a","b")
sub abc {
$first=$_[0];
$second=$_[1];
....
}
abc("a","b")
abc函数中有a,b两个参数
$_[0]的值就是a
$_[1]的值就是b
可以这样来加深理解
&abc("a","b")
sub abc {
$first=$_[0];
$second=$_[1];
print $first.$second;
}
$_[0]表示函数的第一个参数
$_[1]表示函数的第二个参数
以此类推.......
$sum1 = my_sum1(1,2);
$sum2 = my_sum2(1,2);
print "sum1 = $sum1 sum2 = $sum2";
sub my_sum1{
($first,$second)=@_;
return($first+$second);
}
sub my_sum2{
$first=$_[0];
$second=$_[1];
return($first+$second);
}
exit;
++++++++++++++++++
Perl的表达是非常灵活的,以上两个函数是等效的,还有其他写法,这里不多举例了,执行结果为:
sum1 = 3 sum2 = 3
第一种写法是比较常见的,第二种是简单直接的写法,你可以只接收你想要的参数,它的好处是如果你接收了一万个参数,你可以用$_[999]来接收第999 个参数,而其他的就不用管。在Perl中,当一个自定义函数接收参数时,它都放在数组@_中,$_[0],$_[1]就是从该数组中去取参数。
其实很简单,所有传入Perl过程的参数都是以@_身份传入的。如果调用一个有两个参数的函数,它们在函数内部可以作为@_数组的前两个成员访问:$_ [0]和$_[1]。因为@_只是一个有着奇怪名字的普通数组,所以你可以像处理普通数组一样随意的处理它,知道了这一点,其他的书写模式也就不奇怪了:
比如:($first,$second)=@_; 就是将数组@_中的两个元素分别付给$first,$second,由于@_是数组,所以将$first,$second用括号括起来表示列表环境。
还有什么$first = shift; $second = shift; 将@_中的第一个元素付给$first,第二个元素付给$second。Perl 中的特殊变量 $&, $`,$' 用在模式匹配中。
$& 用来存放匹配中的值
$` 用来存放匹配中之前所有字符
$' 用来存放匹配中之后所有字符
if("Hello good there,neigbor hello" =~ /\S\w+,/){
print "That actually matched '$&'. ";
print $`." ";
print $'." ";
}
执行的结果为:
That actually matched 'there,'.
Hello good
neigbor hello
---------------------------
另外常用的变量@_
@_ 是子程序的一个私有变量;如果有一个全局变量@_,它将在此子程序调用前存储起来,当子程序调用完成后,其早期的值会被重新赋还给@_。这意味着当将参数传递给子程序时不用担心它会影响此程序中其它子程序的@_这个变量的值。嵌套的子程序调用时,@_的值和上述类似。甚至此子程序递归调用时,每一次调用将得到新的@_,因此子程序调用时将得到其自身的参数列表。
除非调用的子程序前有&而后面没有括号(或者没有参数),此时@_从此调用者的上下文(context)得到。这通常不是个好主意,但有时很有用。
六、打开管道
用程序的形式也可以象命令行一样打开和使用管道(ex:ls>tempfile)。如语句open (MYPIPE, "| cat >hello"); 打开一个管道,发送到MYPIPE的输出成为命令"cat >hello"的输入。由于cat命令将显示输入文件的内容,故该语句等价于open(MYPIPE, ">hello"); 用管道发送邮件如下:
open (MESSAGE, "| mail dave");
print MESSAGE ("Hi, Dave! Your Perl program sent this!\n");
close (MESSAGE);
七、相关的文件、目录操作函数
open函数
以下是语法打开file.txt写入模式。这里比>signe少表示该文件是以写入模式打开。
open(DATA, ">file.txt");
这个例子实际上截断(清空)文件打开前用于写入,这可能不是预期的效果。如果你想打开一个文件进行读取和写入,你可以把前一个加号>或<字符。
例如,要为更新打开一个文件而不会截断它:
open(DATA, "+<file.txt");
首先要截断该文件:
open DATA, "+>file.txt" or die "Couldn't open file file.txt, $!";
可以在追加模式打开一个文件。在这种模式下写入指向将被设置到文件的末尾。
open(DATA,">>file.txt") || die "Couldn't open file file.txt, $!";
双重>>符号表示打开追加文件,文件指针放置在结尾,让你可以立即开始追加信息。然而,你不能读取它,除非你也将在它前面的加号:
open(DATA,"+>>file.txt") || die "Couldn't open file file.txt, $!";
以下是表了不同模式的可能值:
Entities Definition < or r Read Only Access - by www.gitbook.net
> or w Creates, Writes, and Truncates
>> or a Writes, Appends, and Creates
+< or r+ Reads and Writes
+> or w+ Reads, Writes, Creates, and Truncates
+>> or a+ Reads, Writes, Appends, and Creates
sysopen函数
sysopen函数是主要open函数相似,但它使用系统open()函数,使用系统函数的参数提供给它的参数:例如,要打开一个文件用于更新,从打开模拟+<文件名格式:
sysopen(DATA, "file.txt", O_RDWR);
或截断,然后再更新文件:
sysopen(DATA, "file.txt", O_RDWR|O_TRUNC );
可以使用O_CREAT创建一个新文件,O_WRONLY只写模式和O_RDONLY打开文件 - 打开文件在只读模式。
PERMS 参数指定指定的文件的权限,如果它要创建,默认情况下是0x666。
Value Definition O_RDWR Read and Write
O_RDONLY Read Only
O_WRONLY Write Only
O_CREAT Create the file
O_APPEND Append the file
O_TRUNC Truncate the file
O_EXCL Stops if file already exists
O_NONBLOCK Non-Blocking usability
close函数
要关闭一个文件句柄,因此脱离了相应的文件句柄,你使用close函数刷新文件句柄的缓冲和关闭系统的文件描述符。
close FILEHANDLE
close
如果没有指定的文件句柄(FILEHANDLE)的话关闭当前选择的文件句柄。只有当它能够成功地刷新缓冲区并关闭该文件,它返回true。
close(DATA) || die "Couldn't close file proPerly";
读取和写入的文件句柄
当你有一个打开文件句柄,你需要能够读取和写入信息。也有一些不同的方式读取和写入文件的数据。
<FILEHANDL> 操作符
从一个打开文件句柄读取信息的主要方法是<FILEHANDLE>操作符,在标量上下文中,它返回一个文件句柄一行。例如:
print "What is your name?\n";
$name = <STDIN>;
print "Hello $name\n";
当您使用<FILEHANDLE>操作符在一个列表上下文,它返回从指定的文件句柄的行列表。例如,导入到一个数组从一个文件的所有行:
open(DATA,"<import.txt") or die "Can't open data";
@lines = <DATA>;
close(DATA);
getc函数
getc函数返回从指定的文件句柄或STDIN,如果没有指定一个单一的字符:
getc FILEHANDLE
getc
如果有错误,或者文件句柄在文件的末尾,然后返回UNDEF。
read函数
read 函数用于从缓冲区的文件句柄读取信息,该函数用于从文件读取二进制数据。
read FILEHANDLE, SCALAR, LENGTH, OFFSET
read FILEHANDLE, SCALAR, LENGTH
参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
SCALAR:存贮结果,如果没有指定OFFSET,数据将放在SCALAR的开头。否则数据放在SCALAR中的OFFSET字节之后。
LENGTH:读取的内容长度。
OFFSET:偏移量。
如果读取成功返回读取的字节数,如果在文件结尾返回 0,如果发生错误返回 undef。
数据读取的长度定义的长度(LENGTH),如果没有偏移指定的数据放置在标量(SCALAR)开始。否则,数据将被放置在标量抵消后的字节。该函数返回零上读取文件结束成功的字节数,或者undef如果有一个错误。
print函数
写入信息反馈的主要功能是为所有不同的方法用于从文件句柄读取信息的打印功能。
print FILEHANDLE LIST
print LIST
print
打印功能打印文件句柄,或当前输出句柄(默认为STDOUT),计算值列表。例如:
print "Hello FreeOA.Net!\n";
拷贝文件
这里是例如打开一个现有的文件file1.txt和读取一行行,并生成另一个副本file2.txt
# Open file to read
open(DATA1, "<file1.txt");
# Open new file to write
open(DATA2, ">file2.txt");
# Copy data from one file to another.
while(<DATA1>){
print DATA2 $_;
}
close( DATA1 );
close( DATA2 );
重命名一个文件
下面是一个例子,它告诉我们如何重命名一个文件file1.txt为file2.txt。假设文件在/usr/test目录。
rename ("/usr/test/file1.txt", "/usr/test/file2.txt" );
这个函数重命名需要两个参数,它只是重命名现有文件。
删除一已存在的文件
下面是一个例子,它展示了如何使用的unlink函数删除一个文件file1.txt。
unlink ("/usr/test/file1.txt");
定位文件中位置
你可以用它来tell 函数知道一个文件的当前位置,seek 函数指向内部文件的特定位置。
tell 函数
可以使用 tell 函数来获取文件的位置,并通过使用 seek 函数来指定文件内的的位置:
tell 函数用于获取文件位置:
tell FILEHANDLE
tell
这将返回文件指针的位置,以字节为单位,如果没有指定,在句柄指定或当前的默认选中的文件句柄。
seek 函数
seek()函数是通过文件句柄来移动文件读写指针的方式来读取或写入文件的,以字节为单位进行读取和写入:
seek FILEHANDLE, POSITION, WHENCE
参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
POSITION:表示文件句柄(读写位置指针)要移动的字节数。
WHENCE:表示文件句柄(读写位置指针)开始移动时的起始位置,可以取的值为0、1、2;分别表示文件开头、当前位置和文件尾。
该函数使用的fseek系统的功能,有同样的相对位置功能,以三个不同点:开始,结束,当前位置。可以通过指定一个值自何处(WHENCE)。零设置相对定位文件开始。例如以下实例为从文件开头读取 256 个字节:
seek DATA, 256, 0;
获取文件信息
你可以测试在Perl中的某些功能使用统称为 - X测试的一系列测试运营商非常快速。例如,进行快速测试的各种文件的权限,你可能会使用这样的脚本:
my (@description,$size);
if (-e $file){
push @description, 'binary' if (-B _);
push @description, 'a socket' if (-S _);
push @description, 'a text file' if (-T _);
push @description, 'a block special file' if (-b _);
push @description, 'a character special file' if (-c _);
push @description, 'a directory' if (-d _); # by www.gitbook.net
push @description, 'executable' if (-x _);
push @description, (($size = -s _)) ? "$size bytes" : 'empty';
print "$file is ", join(', ',@description),"\n";
}
这里是功能列表,可以检查文件(下面提供了中英文参考):
Operator Description
-A Age of file (at script startup) in days since modification.
-B Is it a binary file?
-C Age of file (at script startup) in days since modification.
-M Age of file (at script startup) in days since modification.
-O Is the file owned by the real user ID?
-R Is the file readable by the real user ID or real group?
-S Is the file a socket?
-T Is it a text file?
-W Is the file writable by the real user ID or real group?
-X Is the file executable by the real user ID or real group?
-b Is it a block special file?
-c Is it a character special file?
-d Is the file a directory?
-e Does the file exist?
-f Is it a plain file? # by www.gitbook.net
-g Does the file have the setgid bit set?
-k Does the file have the sticky bit set?
-l Is the file a symbolic link?
-o Is the file owned by the effective user ID?
-p Is the file a named pipe?
-r Is the file readable by the effective user or group ID?
-s Returns the size of the file, zero size = empty file.
-t Is the filehandle opened by a TTY (terminal)?
-u Does the file have the setuid bit set?
-w Is the file writable by the effective user or group ID?
-x Is the file executable by the effective user or group ID?
-z Is the file size zero?
操作符 描述
-A 文件上一次被访问的时间(单位:天)
-B 是否为二进制文件
-C 文件的(inode)索引节点修改时间(单位:天)
-M 文件上一次被修改的时间(单位:天)
-O 文件被真实的UID所有
-R 文件或目录可以被真实的UID/GID读取
-S 为socket(套接字)
-T 是否为文本文件
-W 文件或目录可以被真实的UID/GID写入
-X 文件或目录可以被真实的UID/GID执行
-b 为block-special (特殊块)文件(如挂载磁盘)
-c 为character-special (特殊字符)文件(如I/O 设备)
-d 为目录
-e 文件或目录名存在
-f 为普通文件
-g 文件或目录具有setgid属性
-k 文件或目录设置了sticky位
-l 为符号链接
-o 文件被有效UID所有
-p 文件是命名管道(FIFO)
-r 文件可以被有效的UID/GID读取
-s 文件或目录存在且不为0(返回字节数)
-t 文件句柄为TTY(系统函数isatty()的返回结果;不能对文件名使用这个测试)
-u 文件或目录具有setuid属性
-w 文件可以被有效的UID/GID写入
-x 文件可以被有效的UID/GID执行
-z 文件存在,大小为0(目录恒为false),即是否为空文件
在目录中工作
以下是通常操作目录的标准功能。
opendir DIRHANDLE, EXPR # To open a directory
readdir DIRHANDLE # To read a directory
rewinddir DIRHANDLE # Positioning pointer to the begining
telldir DIRHANDLE # Returns current position of the dir
seekdir DIRHANDLE, POS # Pointing pointer to POS inside dir
closedir DIRHANDLE # Closing a directory.
下面是一个例子,它打开一个目录,并列出此目录内的所有文件:
opendir (DIR, '.') or die "Couldn't open directory, $!";
while ($file = readdir DIR){
print "$file\n";
}
closedir DIR;
另一个例子,打印C源代码文件列表,可以使用:
opendir(DIR, '.') or die "Couldn't open directory, $!";
foreach (sort grep(/^.*\.c$/,readdir(DIR))){
print "$_\n";
}
closedir DIR;
使用mkdir 函数可以创建一个新的目录,使用rmdir 函数可以删除一个目录,使用chdir函数来改变一个目录。
二、读文件
三、写文件
四、判断文件状态
五、命令行参数
六、打开管道
七、相关的文件、目录操作函数
处理文件的基本原理很简单:你关联与外部实体(通常是文件)的文件句柄,然后使用各种在Perl的运算符和函数内与句柄相关联的数据流中存储的数据读取和更新。一个句柄是一个名为Perl的内部结构,关联物理文件名称。所有的文件句柄是读/写访问,所以你可以读取和更新与句柄相关联的任何文件或设备的能力。然而,当你关联的文件句柄,你可以在被打开的文件句柄指定的模式。
三个基本文件的句柄是:STDIN, STDOUT 和 STDERR.
一、打开、关闭文件
语法为:open(filevar, filename),其中filevar为文件句柄,或者说是程序中用来代表某文件的代号,filename为文件名,其路径可为相对路径,亦可为绝对路径。
open(FILE1,"file1");
open(FILE1, "/u/jqpublic/file1");
打开文件时必须决定访问模式,在Perl中有三种访问模式:读、写和添加。后两种模式的区别在于写模式将原文件覆盖,原有内容丢失,形式为:open (outfile,">outfile");而添加模式则在原文件的末尾处继续添加内容,形式为:open(appendfile, ">>appendfile")。要注意的是:不能对文件同时进行读和写/添加操作。
open的返回值用来确定打开文件的操作是否成功,当其成功时返回非零值,失败时返回零,因此可以如下判断:
if (open(MYFILE, "myfile")) {
# here's what to do if the file opened successfully
}
当文件打开失败时结束程序:
unless (open (MYFILE, "file1")) {
die ("cannot open input file file1\n");
}
亦可用逻辑或操作符表示如下:
open (MYFILE, "file1") || die ("Could not open file");
当文件操作完毕后,用close(MYFILE); 关闭文件。
Per有以下两个函数以及多形式可以用来打开任何新的或现有的文件。
open FILEHANDLE, EXPR
open FILEHANDLE
sysopen FILEHANDLE, FILENAME, MODE, PERMS
sysopen FILEHANDLE, FILENAME, MODE
参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
EXPR:文件名及文件访问类型组成的表达式。
MODE:文件访问类型。
PERMS:访问权限位(permission bits)。
这里的FILEHANDLE是由open函数返回的文件句柄和expr是打开文件的文件名和模式的表达式。以下是语法在只读模式打开file.txt的。下面表明该文件是只读模式打开:
open(DATA, "<file.txt");
二、读文件
语句$line =<>;从文件中读取一行数据存储到简单变量$line中并把文件指针向后移动一行。为标准输入文件,通常为键盘输入,不需要打开。语句@array = <>;把文件的全部内容读入数组@array,文件的每一行(含回车符)为@array的一个元素。
perl中使用一对尖括号格式的<STDIN>来读取来自非文件的标准输入,例如来自管道的数据,来自输入重定向的数据或者来自键盘的输入。需要注意的是,<STDIN>读取的输入会自带换行符,所以print输出的时候不要加上额外的换行符。
三、写文件
形式为:
open(OUTFILE, ">outfile");
print OUTFILE ("Here is an output line.\n");
注:STDOUT、STDERR为标准输出和标准错误文件,通常为屏幕,且不需要打开。
四、判断文件状态
1、文件测试操作符
语法为:-op expr,如:
if (-e "/path/file1") {
print STDERR ("File file1 exists.\n");
}
文件测试操作符
操作符 描述
-b 是否为块设备
-c 是否为字符设备
-d 是否为目录
-e 是否存在
-f 是否为普通文件
-g 是否设置了setgid位
-k 是否设置了sticky位
-l 是否为符号链接
-o 是否拥有该文件
-p 是否为管道
-r 是否可读
-s 是否非空
-t 是否表示终端
-u 是否设置了setuid位
-w 是否可写
-x 是否可执行
-z 是否为空文件
-A 距上次访问多长时间
-B 是否为二进制文件
-C 距上次访问文件的inode多长时间
-M 距上次修改多长时间
-O 是否只为“真正的用户”所拥有
-R 是否只有“真正的用户”可读
-S 是否为socket
-T 是否为文本文件
-W 是否只有"真正的用户"可写
-X 是否只有"真正的用户"可执行
注:“真正的用户”指登录时指定的userid,与当前进程用户ID相对,命令suid可以改变有效用户ID。例:
unless (open(INFILE, "infile")) {
die ("Input file infile cannot be opened.\n");
}
if (-e "outfile") {
die ("Output file outfile already exists.\n");
}
unless (open(OUTFILE, ">outfile")) {
die ("Output file outfile cannot be opened.\n");
}
等价于
open(INFILE, "infile") && !(-e "outfile") &&
open(OUTFILE, ">outfile") || die("Cannot open files\n");
五、命令行参数的解释
象C一样,Perl也有存储命令行参数的数组@ARGV,可以用来分别处理各个命令行参数;与C不同的是,$ARGV[0]是第一个参数,而不是程序名本身。
$var = $ARGV[0]; # 第一个参数
$numargs = @ARGV; # 参数的个数
Perl中,操作符实际上是对数组@ARGV的隐含的引用,其工作原理为:
1、当Perl解释器第一次看到时,打开以$ARGV[0]为文件名的文件;
2、执行动作shift(@ARGV); 即把数组@ARGV的元素向前移动一个,其元素数量即减少了一个。
3、操作符读取在第一步打开的文件中的所有行。
4、读完后,解释器回到第一步重复。
@ARGV = ("myfile1", "myfile2"); #实际上由命令行参数赋值
while ($line = <>) {
print ($line);
}
将把文件myfile1和myfile2的内容打印出来。
函数的参数
&abc("a","b")
sub abc {
$first=$_[0];
$second=$_[1];
....
}
abc("a","b")
abc函数中有a,b两个参数
$_[0]的值就是a
$_[1]的值就是b
可以这样来加深理解
&abc("a","b")
sub abc {
$first=$_[0];
$second=$_[1];
print $first.$second;
}
$_[0]表示函数的第一个参数
$_[1]表示函数的第二个参数
以此类推.......
$sum1 = my_sum1(1,2);
$sum2 = my_sum2(1,2);
print "sum1 = $sum1 sum2 = $sum2";
sub my_sum1{
($first,$second)=@_;
return($first+$second);
}
sub my_sum2{
$first=$_[0];
$second=$_[1];
return($first+$second);
}
exit;
++++++++++++++++++
Perl的表达是非常灵活的,以上两个函数是等效的,还有其他写法,这里不多举例了,执行结果为:
sum1 = 3 sum2 = 3
第一种写法是比较常见的,第二种是简单直接的写法,你可以只接收你想要的参数,它的好处是如果你接收了一万个参数,你可以用$_[999]来接收第999 个参数,而其他的就不用管。在Perl中,当一个自定义函数接收参数时,它都放在数组@_中,$_[0],$_[1]就是从该数组中去取参数。
其实很简单,所有传入Perl过程的参数都是以@_身份传入的。如果调用一个有两个参数的函数,它们在函数内部可以作为@_数组的前两个成员访问:$_ [0]和$_[1]。因为@_只是一个有着奇怪名字的普通数组,所以你可以像处理普通数组一样随意的处理它,知道了这一点,其他的书写模式也就不奇怪了:
比如:($first,$second)=@_; 就是将数组@_中的两个元素分别付给$first,$second,由于@_是数组,所以将$first,$second用括号括起来表示列表环境。
还有什么$first = shift; $second = shift; 将@_中的第一个元素付给$first,第二个元素付给$second。Perl 中的特殊变量 $&, $`,$' 用在模式匹配中。
$& 用来存放匹配中的值
$` 用来存放匹配中之前所有字符
$' 用来存放匹配中之后所有字符
if("Hello good there,neigbor hello" =~ /\S\w+,/){
print "That actually matched '$&'. ";
print $`." ";
print $'." ";
}
执行的结果为:
That actually matched 'there,'.
Hello good
neigbor hello
---------------------------
另外常用的变量@_
@_ 是子程序的一个私有变量;如果有一个全局变量@_,它将在此子程序调用前存储起来,当子程序调用完成后,其早期的值会被重新赋还给@_。这意味着当将参数传递给子程序时不用担心它会影响此程序中其它子程序的@_这个变量的值。嵌套的子程序调用时,@_的值和上述类似。甚至此子程序递归调用时,每一次调用将得到新的@_,因此子程序调用时将得到其自身的参数列表。
除非调用的子程序前有&而后面没有括号(或者没有参数),此时@_从此调用者的上下文(context)得到。这通常不是个好主意,但有时很有用。
六、打开管道
用程序的形式也可以象命令行一样打开和使用管道(ex:ls>tempfile)。如语句open (MYPIPE, "| cat >hello"); 打开一个管道,发送到MYPIPE的输出成为命令"cat >hello"的输入。由于cat命令将显示输入文件的内容,故该语句等价于open(MYPIPE, ">hello"); 用管道发送邮件如下:
open (MESSAGE, "| mail dave");
print MESSAGE ("Hi, Dave! Your Perl program sent this!\n");
close (MESSAGE);
七、相关的文件、目录操作函数
open函数
以下是语法打开file.txt写入模式。这里比>signe少表示该文件是以写入模式打开。
open(DATA, ">file.txt");
这个例子实际上截断(清空)文件打开前用于写入,这可能不是预期的效果。如果你想打开一个文件进行读取和写入,你可以把前一个加号>或<字符。
例如,要为更新打开一个文件而不会截断它:
open(DATA, "+<file.txt");
首先要截断该文件:
open DATA, "+>file.txt" or die "Couldn't open file file.txt, $!";
可以在追加模式打开一个文件。在这种模式下写入指向将被设置到文件的末尾。
open(DATA,">>file.txt") || die "Couldn't open file file.txt, $!";
双重>>符号表示打开追加文件,文件指针放置在结尾,让你可以立即开始追加信息。然而,你不能读取它,除非你也将在它前面的加号:
open(DATA,"+>>file.txt") || die "Couldn't open file file.txt, $!";
以下是表了不同模式的可能值:
Entities Definition < or r Read Only Access - by www.gitbook.net
> or w Creates, Writes, and Truncates
>> or a Writes, Appends, and Creates
+< or r+ Reads and Writes
+> or w+ Reads, Writes, Creates, and Truncates
+>> or a+ Reads, Writes, Appends, and Creates
sysopen函数
sysopen函数是主要open函数相似,但它使用系统open()函数,使用系统函数的参数提供给它的参数:例如,要打开一个文件用于更新,从打开模拟+<文件名格式:
sysopen(DATA, "file.txt", O_RDWR);
或截断,然后再更新文件:
sysopen(DATA, "file.txt", O_RDWR|O_TRUNC );
可以使用O_CREAT创建一个新文件,O_WRONLY只写模式和O_RDONLY打开文件 - 打开文件在只读模式。
PERMS 参数指定指定的文件的权限,如果它要创建,默认情况下是0x666。
Value Definition O_RDWR Read and Write
O_RDONLY Read Only
O_WRONLY Write Only
O_CREAT Create the file
O_APPEND Append the file
O_TRUNC Truncate the file
O_EXCL Stops if file already exists
O_NONBLOCK Non-Blocking usability
close函数
要关闭一个文件句柄,因此脱离了相应的文件句柄,你使用close函数刷新文件句柄的缓冲和关闭系统的文件描述符。
close FILEHANDLE
close
如果没有指定的文件句柄(FILEHANDLE)的话关闭当前选择的文件句柄。只有当它能够成功地刷新缓冲区并关闭该文件,它返回true。
close(DATA) || die "Couldn't close file proPerly";
读取和写入的文件句柄
当你有一个打开文件句柄,你需要能够读取和写入信息。也有一些不同的方式读取和写入文件的数据。
<FILEHANDL> 操作符
从一个打开文件句柄读取信息的主要方法是<FILEHANDLE>操作符,在标量上下文中,它返回一个文件句柄一行。例如:
print "What is your name?\n";
$name = <STDIN>;
print "Hello $name\n";
当您使用<FILEHANDLE>操作符在一个列表上下文,它返回从指定的文件句柄的行列表。例如,导入到一个数组从一个文件的所有行:
open(DATA,"<import.txt") or die "Can't open data";
@lines = <DATA>;
close(DATA);
getc函数
getc函数返回从指定的文件句柄或STDIN,如果没有指定一个单一的字符:
getc FILEHANDLE
getc
如果有错误,或者文件句柄在文件的末尾,然后返回UNDEF。
read函数
read 函数用于从缓冲区的文件句柄读取信息,该函数用于从文件读取二进制数据。
read FILEHANDLE, SCALAR, LENGTH, OFFSET
read FILEHANDLE, SCALAR, LENGTH
参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
SCALAR:存贮结果,如果没有指定OFFSET,数据将放在SCALAR的开头。否则数据放在SCALAR中的OFFSET字节之后。
LENGTH:读取的内容长度。
OFFSET:偏移量。
如果读取成功返回读取的字节数,如果在文件结尾返回 0,如果发生错误返回 undef。
数据读取的长度定义的长度(LENGTH),如果没有偏移指定的数据放置在标量(SCALAR)开始。否则,数据将被放置在标量抵消后的字节。该函数返回零上读取文件结束成功的字节数,或者undef如果有一个错误。
print函数
写入信息反馈的主要功能是为所有不同的方法用于从文件句柄读取信息的打印功能。
print FILEHANDLE LIST
print LIST
打印功能打印文件句柄,或当前输出句柄(默认为STDOUT),计算值列表。例如:
print "Hello FreeOA.Net!\n";
拷贝文件
这里是例如打开一个现有的文件file1.txt和读取一行行,并生成另一个副本file2.txt
# Open file to read
open(DATA1, "<file1.txt");
# Open new file to write
open(DATA2, ">file2.txt");
# Copy data from one file to another.
while(<DATA1>){
print DATA2 $_;
}
close( DATA1 );
close( DATA2 );
重命名一个文件
下面是一个例子,它告诉我们如何重命名一个文件file1.txt为file2.txt。假设文件在/usr/test目录。
rename ("/usr/test/file1.txt", "/usr/test/file2.txt" );
这个函数重命名需要两个参数,它只是重命名现有文件。
删除一已存在的文件
下面是一个例子,它展示了如何使用的unlink函数删除一个文件file1.txt。
unlink ("/usr/test/file1.txt");
定位文件中位置
你可以用它来tell 函数知道一个文件的当前位置,seek 函数指向内部文件的特定位置。
tell 函数
可以使用 tell 函数来获取文件的位置,并通过使用 seek 函数来指定文件内的的位置:
tell 函数用于获取文件位置:
tell FILEHANDLE
tell
这将返回文件指针的位置,以字节为单位,如果没有指定,在句柄指定或当前的默认选中的文件句柄。
seek 函数
seek()函数是通过文件句柄来移动文件读写指针的方式来读取或写入文件的,以字节为单位进行读取和写入:
seek FILEHANDLE, POSITION, WHENCE
参数说明:
FILEHANDLE:文件句柄,用于存放一个文件唯一标识符。
POSITION:表示文件句柄(读写位置指针)要移动的字节数。
WHENCE:表示文件句柄(读写位置指针)开始移动时的起始位置,可以取的值为0、1、2;分别表示文件开头、当前位置和文件尾。
该函数使用的fseek系统的功能,有同样的相对位置功能,以三个不同点:开始,结束,当前位置。可以通过指定一个值自何处(WHENCE)。零设置相对定位文件开始。例如以下实例为从文件开头读取 256 个字节:
seek DATA, 256, 0;
获取文件信息
你可以测试在Perl中的某些功能使用统称为 - X测试的一系列测试运营商非常快速。例如,进行快速测试的各种文件的权限,你可能会使用这样的脚本:
my (@description,$size);
if (-e $file){
push @description, 'binary' if (-B _);
push @description, 'a socket' if (-S _);
push @description, 'a text file' if (-T _);
push @description, 'a block special file' if (-b _);
push @description, 'a character special file' if (-c _);
push @description, 'a directory' if (-d _); # by www.gitbook.net
push @description, 'executable' if (-x _);
push @description, (($size = -s _)) ? "$size bytes" : 'empty';
print "$file is ", join(', ',@description),"\n";
}
这里是功能列表,可以检查文件(下面提供了中英文参考):
Operator Description
-A Age of file (at script startup) in days since modification.
-B Is it a binary file?
-C Age of file (at script startup) in days since modification.
-M Age of file (at script startup) in days since modification.
-O Is the file owned by the real user ID?
-R Is the file readable by the real user ID or real group?
-S Is the file a socket?
-T Is it a text file?
-W Is the file writable by the real user ID or real group?
-X Is the file executable by the real user ID or real group?
-b Is it a block special file?
-c Is it a character special file?
-d Is the file a directory?
-e Does the file exist?
-f Is it a plain file? # by www.gitbook.net
-g Does the file have the setgid bit set?
-k Does the file have the sticky bit set?
-l Is the file a symbolic link?
-o Is the file owned by the effective user ID?
-p Is the file a named pipe?
-r Is the file readable by the effective user or group ID?
-s Returns the size of the file, zero size = empty file.
-t Is the filehandle opened by a TTY (terminal)?
-u Does the file have the setuid bit set?
-w Is the file writable by the effective user or group ID?
-x Is the file executable by the effective user or group ID?
-z Is the file size zero?
操作符 描述
-A 文件上一次被访问的时间(单位:天)
-B 是否为二进制文件
-C 文件的(inode)索引节点修改时间(单位:天)
-M 文件上一次被修改的时间(单位:天)
-O 文件被真实的UID所有
-R 文件或目录可以被真实的UID/GID读取
-S 为socket(套接字)
-T 是否为文本文件
-W 文件或目录可以被真实的UID/GID写入
-X 文件或目录可以被真实的UID/GID执行
-b 为block-special (特殊块)文件(如挂载磁盘)
-c 为character-special (特殊字符)文件(如I/O 设备)
-d 为目录
-e 文件或目录名存在
-f 为普通文件
-g 文件或目录具有setgid属性
-k 文件或目录设置了sticky位
-l 为符号链接
-o 文件被有效UID所有
-p 文件是命名管道(FIFO)
-r 文件可以被有效的UID/GID读取
-s 文件或目录存在且不为0(返回字节数)
-t 文件句柄为TTY(系统函数isatty()的返回结果;不能对文件名使用这个测试)
-u 文件或目录具有setuid属性
-w 文件可以被有效的UID/GID写入
-x 文件可以被有效的UID/GID执行
-z 文件存在,大小为0(目录恒为false),即是否为空文件
在目录中工作
以下是通常操作目录的标准功能。
opendir DIRHANDLE, EXPR # To open a directory
readdir DIRHANDLE # To read a directory
rewinddir DIRHANDLE # Positioning pointer to the begining
telldir DIRHANDLE # Returns current position of the dir
seekdir DIRHANDLE, POS # Pointing pointer to POS inside dir
closedir DIRHANDLE # Closing a directory.
下面是一个例子,它打开一个目录,并列出此目录内的所有文件:
opendir (DIR, '.') or die "Couldn't open directory, $!";
while ($file = readdir DIR){
print "$file\n";
}
closedir DIR;
另一个例子,打印C源代码文件列表,可以使用:
opendir(DIR, '.') or die "Couldn't open directory, $!";
foreach (sort grep(/^.*\.c$/,readdir(DIR))){
print "$_\n";
}
closedir DIR;
使用mkdir 函数可以创建一个新的目录,使用rmdir 函数可以删除一个目录,使用chdir函数来改变一个目录。