1. 文件测试操作符
warning "Oops, A file called '$filename' already exists。\n" if -e $filename;
warning "Config file is looking pretty old!\n" if -M CONFIG >28
将超过90天没有访问,且大于100KB的文件归档到磁带。
my @original_files = qw /Fred barney betty/;
my @big_old_files;
foreach my $filename (@original_files) {
#这里使用my,则$filename就在循环块中有效
push @big_old_files, $filename
if -s $filename > 100_000 and -A $filename > 90;
}
$my_file_size_inM = ( -s $filename ) / ( 1024 * 1024 )
#一定要用括号扩起来
如果需要对一个文件进行多项属性测试,用虚拟文件句柄_来使用上次查询过的文件来做当前的测试。例如
if( -r $file and -w _)
{...}
或者使用栈式文件操作符:
if( -w -r $file ) {...}
#最靠近文件名的操作符会最先执行
但是涉及到返回值的不要用栈式操作符,例如
if( -s -d $filename < 512 ) {...}
#等同于
if( ( -d $file and -s _ ) < 512 ) {...}
文件操作符(转自http://bdxnote.blog.163.com/blog/static/84442352008317113915957/)
一、文件权限测试
UNIX和LINUX系统中有用户ID和组ID,Windows系统中有用户名和组名,它们的含义分别相同;在UNIX/LINUX系统中,用户ID和组ID都有两种:有效ID和实际ID;登录系统时所使用的ID是实际ID,而有效ID则是当前执行进程的ID,可以在执行程序期间改变;如果Perl5程序要复位用户ID和组ID,那么新的用户ID和组ID就会成为进程的有效ID;有效ID常用于对进程提供更多文件访问权限,但是每个文件的有效ID和实际ID有不同的权限;
操作符 描述
-r 是否可读
-w 是否可写
-x 是否可执行
-o 是否拥有该文件
-R 是否只有“真正的用户”可读
-W 是否只有“真正的用户”可写
-X 是否只有“真正的用户”可执行
-O 是否只有“真正的用户”拥有该文件
注:“真正的用户”是指登录时指定的UserID(实际ID),与当前进程用户ID(有效ID)相对;命令suid可以改变有效用户ID;
二、文件粘贴位(sticky)
有三个操作符来判断文件的粘贴位;
操作符 描述
-u 是否设置了setuid位
-g 是否设置了setgid位
-k 是否设置了sticky(粘贴)位
三、文件类型判断操作符
操作符 描述
-f 是否是普通文件
-d 是否是目录文件
-l 是否是符号连接文件
-T 是否是文本文件
-B 是否是二进制文件
-b 是否是块设备
-c 是否是字符设备
四、文件的存在性和长度测试
操作符 描述
-e 文件是否存在
-s 文件是否非空
-z 文件是否为空文件
五、文件修改测试
操作符 描述
-A 距上次访问多长时间
-C 距上次访问文件的inode多长时间
-M 距上次修改多长时间
六、UNIX/LINUX文件句柄类型测试
操作符 描述
-p 是否为管道
-s 是否为Socket
-t 是否表示终端
2. stat函数:返回文件属性信息。
lstat返回符号连结本身的信息,如果不是符号链接则返回空列表。
0 dev 设备号 驱动器号(C:通常是2,D:通常是3,等等)
1 ino 索引节号 总是0
2 mode 文件的方式 就是-rwxr-xr-x前9个权限位。可以用8进制来进行逻辑运算。
3 nlink 链接号 通常为0;Windows 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
例:获取文件时间
my @array = stat("mysql.tar.gz");
print "$array[9]\n";
use File::stat;
$st = stat($file) or die "No $file: $!";
if ( ($st->mode & 0111) && $st->nlink > 1) ) {
print "$file is executable with lots of links\n";
}
if ( -x $st ) {
print "$file is executable\n";
}
use Fcntl "S_IRUSR";
if ( $st->cando(S_IRUSR, 1) ) {
print "My effective uid can read $file\n";
}
use File::stat qw(:FIELDS);
stat($file) or die "No $file: $!";
if ( ($st_mode & 0111) && ($st_nlink > 1) ) {
print "$file is executable with lotsa links\n";
}
3.localtime格式化时间戳信息,例如从stat中得到的。
my($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime $timestamp;
4. 逻辑运算符包括& | ^ << >> ~(按位取反)
5.文件与目录操作
在目录树中移动chdir "/etc" or dir "cannot chdir to /etc:$!";
使用类似SHELL下的通配符*: my @all_files = glob "*"或者my @all_files = glob "*"
my @dir_files = <$dir/*>
#注意不带*的<>都会被perl认为是间接文件句柄读取,或者使用readline $dir_file[1];
目录句柄
my $dir_to_process = "/etc";
opendir DH, $dir_to_process or die "Cannot open $dir_to_process: $!";
foreach $file (readdir DH) {
next unless $name =~ /\.pm$/;
print "one file in $dir_to_process is $file\n";
}
closedir DH;
unlink=rm rename=mv link=ln mkdir rmdir chmod chown需要的是一个数字ID号,需要用getpwnaw将字符串转换成id
defined(my $user = getpwnam "merlyn") or die "bad user";
defined(my $group = getgrnam "Users") or die "bad group";
chown $user, $group, glob "/home/merlyn/*";
修改时间戳来进行欺骗:
my $now = time;
my $ago = $now ? 24 * 60 * 60;
utime $now, $ago, glob "*";
6. 智能匹配操作符
my $flag = 0
foreach my $key ( keys %name ) {
next unless $key =~ /Fred/;
$flag = $key;
last;
}
可以直接用智能匹配运算符来实现:cammand if %names ~~ /Fred/;
数组的比较:print "The arrays have the same elements!" if @names1 ~~ @names2
元素是否在数组中:print "the $result is one of nums" if @nums ~~ $result
智能匹配对不同操作数的处理方式:
%a ~~ %b
哈希的键是否一致
%a ~~ @b
至少%a中的一个键在列表@b之中。
%a ~~ /Fred/
至少一个键匹配给定的模式
%a ~~ 'Fred'
哈希的$a{Fred}是否存在
@a ~~ @b
@a ~~ /Fred/
@a ~~ 123
@a ~~ 'Fred'
$name ~~ undef
$name ~~ /Fred/
模式匹配
123 ~~ '123.0'
数字和字符串是否大小相等。
'Fred' ~~ 'Fred'字符串是否完全相等
123 ~~ 123
数字大小完全相等
7. given语句同switch语句
given ( $ARGV[0] ) {
when( /fred/i ){}
...
default{}
}
given ( $ARGV[0] ) {
when( $_ ~~ /fred/i){; continue;或者break;}
...
}
8. system函数
system 'ls -l $HOME' “ls -l \$HOME”
#注意,$HOME是SHELL变量,而不是perl�炔灞淞�
如果执行的命令过长,那么perl就会在这个命令处暂停的时间很长。所以应该在末尾加上&号,让shell将它变成后台进程并立即退出。
exec函数
同shell中的exec函数,这时候原本perl程序的进程空间会被装入exec运行的程序。
环境变量%ENV
$ENV{‘IFS’};
用反引号``捕获输出结果
@who_lines=`who`;
自动拆分成多行数据。
defined(my $pid = fork) or die "cannot fork:$!";
unless ($pid) {
#子进程操作
exec "date";
}
#父进程操作
waitpid($pid, 0);
用kill发送信号量 kill 2, 4201 or die "Cannot signal 4201 with SIGINT: $!";
用%SIG设置信号处理程序:
sub my_int_handler{
...
}
$SIG{'INT'}='my_int_handler';
#哈希键是信号名,不用前缀SIG。值是中断处理程序名,不需要&号。
9. 将进程视为文件句柄
Perl可以使用操作系统提供的管道通信机制,启动一个异步运行的子进并和它保持通信。直到子进程结束执行为止。
open DATE "date|" or die "cannot pipe from date: $!";
open MAIL "|mail merlyn" or die "cannot pipe to mail: $!";
my $now = <DATE>;
print MAIL "The time is now $now";
cloes MAIL;
即可, EOF会输出到写进程里。
10.用eval{}块捕获异常,避免整个程序都会异常退出。例如
eval{
$val = 5/0;
}
print "An error occurred: $@" if $@;
文件打开过程中会有错误,可以在循环打开文件中使用eval。
eval
函数的返回值都是小程序的最后一条语句的值,如果遇到
return
语句,与子例程相同。
11. 用grep来筛选列表
my @odd_number;
foreach (1..1000) {
push @odd_numbers, $_ if $_ %2;
}
可以grep{$_ % 2} 1..1000;
my @matching_lines = grep { /bfred\b/i } <FILE>;
12.用map对列表进行转换
例如:@newdata = map { sprintf("%25s\n", &big_money($_) ) } @data;
13.切片
在读取以:分割的字符串时,可以直接引入 例如 (split /:/)[4];
(stat $some_file)[9];
数组切片@names[2,5]等同于($names[2], $names[5]);
哈希切片@names{@players}或者@names{'fred','cowerd'};这里还要使用@