perl 高阶语法

perl栏分为perl基本语法、高阶语法、和一个perl自动化脚本生成器案例。

语法部分是笔者学习perl的总结,并非原创。

案例是笔者原创。

perl 高阶语法

Contents

print 6

语法. 6

文件句柄. 6

打开文件句柄. 6

标量变量中的文件句柄. 7

返回文件句柄. 7

glob函数. 8

描述. 8

语法. 8

perl regular expression 9

形式. 9

匹配. 9

替换. 9

转化. 9

模式匹配修饰符. 10

正则表达式变量. 10

替换操作符. 11

转化操作符. 11

更多正则表达式规则. 12

反向引用. 14

表达式文本可用符号. 15

应用. 15

模块. 16

localtime模块. 16

scalar(localtime) 16

时间格式化输出. 16

模块stat 17

定义. 17

案例. 17

模块File::Spec 19

示例. 19

辨析print、say、sprintf、printf 20

print 20

say 20

printf 21

sprintf 21

ARGV说明. 22

@ARGV数组. 22

perl用来解析@ARGV的模块. 23

关于Getoptions函数的补充说明. 25

perl模块 Getopt::Long解析参数. 26

选项解析. 27

其他用法. 28

多命名选项. 28

捆绑选项. 28

‘-’ 和 ‘<>’ 30

$#ARGV 32

return和print区别. 32

while和foreach读取文件内容. 33

perl中常用命令. 33

grep 34

Grep vs. loops open FILE "<myfile" or die "Can't open myfile: $!"; print grep /terrorism|nuclear/i, <FILE>;; 35

符号辨识. 35

!!$var 35

defined$var 35

exists $var 35

$variable 36

多维哈希. 36

定义. 36

打印. 37

删除. 39

遍历. 39

引用. 40

拷贝. 40

ref函数. 42

说明. 42

举例. 43

函数. 45

函数的声明与定义. 45

函数的调用方式. 45

通过函数名直接调用. 45

使用前置&号调用. 45

使用引用调用. 46

文件、目录类型判断. 46

文件相关. 46

逻辑表达式组合. 47

文件读写操作. 47

文件. 47

1.1open-close 47

1.2读写文件. 48

1.3文件位置. 48

1.4文件信息. 48

md5加密算法. 49


高阶语法

print

语法

print “”;                # 打印内容到默认终端

print HANDLE “cmd”;      # 打印cmd内容到文件句柄HADNLE指向的地址

print $handle_file <HANDLE>; # 将文件句柄HANDLE指向的地址内容写到变量文件句柄$handle_file指向的地址中

将内容打印到句柄HANDLE指向的终端处,print将内容输出到显示终端是一种特殊形式

文件句柄

Perl进程与外界之间的IO联系的名称,在Perl5.6之前,所有文件句柄名称都是裸子,之后可以把文件句柄的引用放在常规变量中。6个特殊文件句柄名是Perl保留的,STDINSTDOUTSTDERRDATAARGVARGVUT

打开文件句柄

三种perl默认文件句柄---STDIN、STDOUT、STDERR,是产生Perl进程的父进程自动打开的文件或设备。

open Filehandler,filename;

示例:

open CONFIG,'dino';      #打开已存在的dino文件,文件中的任何内容都可以读到我们的程序中

open CONFIG,'<dino';     #用小于号声明该文件只是用来读入,而非写入

open BEDROCK,‘>fred’;  #大于号,打开文件句柄,并输出到新文件fred中,如果已存在fred,则清除原内容并以新内容取代之;

open LOG,'>>logfile';    #双大于号,打开文件,如果文件原本就存在,那么新数据会添加在原有内容后面,如果不存在,会创建一个新文件。

open CONFIG,'<','dino';

open BEDROCK,'>',$file_name;

open LOG,'>>','logfile';

open CONFIG,'<:encoding(UTF-8)','dino';     ##open CONFIG,'<:utf8','dino';

标量变量中的文件句柄

示例:

my $rocks_fh;

open $rocks_fh,'<','rocks.txt' or die "Could not open rocks.txt:$!";

while(<rocks_fh>){

    chomp;

....

}

close $rocks_fh;

返回文件句柄

1、使用\*

#!/usr/bin/perl

use strict;

sub openfile()

{    

    my $path=shift;#把数组的第一个值移出并返回它,然后把数组长度减一并把所有的东西都顺移

    open(FILE,"$path") or die "Can't open $path $!\n ";

    return \*FILE;

}

my $temp=&openfile("config");

my @file=<$temp>;

print @file;

2、使用变量

示例:

#!/usr/bin/perl

use strict;

sub openfile()

{

    my $file;

    my $path=shift;

    open($file,"$path") or die "Can't open $path $!\n ";

   

    #close($file);

    return $file;

   

}

my $temp=&openfile("config");

my @file=<$temp>;

print @file;

glob函数

描述

此函数返回与EXPR匹配的文件的列表,这些文件将由标准Bourne shell进行扩展。如果EXPR未指定路径,请使用当前目录。如果省略EXPR,则使用$_的值。

从Perl 5.6开始,扩展是在内部完成的,而不是使用外部脚本。扩展遵循csh(以及任何派生形式,包括tcsh和bash)的扩展方式,其翻译如下:

  • 以单个句点开头的文件将被忽略,除非EXPR明确匹配。
  • *字符与零个或多个任何类型的字符匹配。
  • 的?字符匹配任何类型的一个字符。
  • [..]构造与正则表达式匹配列出的字符,包括范围。
  • 〜字符与主目录匹配; 〜name与用户名的主目录匹配。
  • {..}构造与括号内的任何逗号分隔的单词匹配。

语法

以下是此函数的简单语法

glob EXPR

glob

返回值

此函数在错误时返回undef,否则在标量context中返回扩展名列表中的第一个文件,在错误时返回空列表,否则返回列表context中扩展名的列表。

以下是显示其基本用法的示例代码-

#!/usr/bin/perl

(@file_list) = glob "perl_g*";

print "Returned list of file @file_list\n";

执行上述代码后,将产生以下输出-

Returned list of file

glob相当于shell中的通配符,有2种形式:

1.@files = glob "*.pl";

2.@files = <*.pl>;perl检查<>中是否是句柄,不是则当成glob处理

#my @file = glob "~/Proj/Perl/*.pl";    #与下句相同

my @file = <~/Proj/Perl/*.pl>;

#my $filestr = "~/Proj/Perl/*.pl";    #<>处理含通配符的变量时,变量需要加{},否则$filestr>会当成变量名

#my @file = <${filestr}>;

foreach(@file){

    print $_."\n";

}

perl regular expression

Perl语言的正则表达式功能非常强大,基本上是常用语言中最强大的,很多语言设计正则式支持的时候都参考Perl的正则表达式。

形式

Perl的正则表达式的三种形式,分别是匹配,替换和转化:

匹配

:m//(还可以简写为//,略去m)

替换

:s///

转化

:tr///

这三种形式一般都和 =~ 或 !~ 搭配使用, =~ 表示相匹配,!~ 表示不匹配。

模式匹配修饰符

模式匹配有一些常用的修饰符,如下表所示:

修饰符

描述

i

忽略模式中的大小写

m

多行模式

o

仅赋值一次

s

单行模式,"."匹配"\n"(默认不匹配)

x

忽略模式中的空白

g

全局匹配

cg

全局匹配失败后,允许再次查找匹配串

正则表达式变量

perl处理完后会给匹配到的值存在三个特殊变量名:

  • $`: 匹配部分的前一部分字符串
  • $&: 匹配的字符串
  • $': 还没有匹配的剩余字符串

如果将这三个变量放在一起,你将得到原始字符串

示例:

#!/usr/bin/perl

$string = "welcome to runoob site.";

$string =~ m/run/;

print "匹配前的字符串: $`\n";

print "匹配的字符串: $&\n";

print "匹配后的字符串: $'\n";

结果:

匹配前的字符串: welcome to

匹配的字符串: run

匹配后的字符串: oob site.

替换操作符

替换操作符 s/// 是匹配操作符的扩展,使用新的字符串替换指定的字符串。基本格式如下:

s/PATTERN/REPLACEMENT/;

替换操作修饰符如下表所示:

修饰符

描述

i

如果在修饰符中加上"i",则正则将会取消大小写敏感性,即"a""A" 是一样的。

m

默认的正则开始"^"和结束"$"只是对于正则字符串如果在修饰符中加上"m",那么开始和结束将会指字符串的每一行:每一行的开头就是"^",结尾就是"$"

o

表达式只执行一次。

s

如果在修饰符中加入"s",那么默认的"."代表除了换行符以外的任何字符将会变成任意字符,也就是包括换行符!

x

如果加上该修饰符,表达式中的空白字符将会被忽略,除非它已经被转义。

g

替换所有匹配的字符串。

e

替换字符串作为表达式

转化操作符

以下是转化操作符相关的修饰符:

修饰符

描述

c

转化所有未指定字符

d

删除所有指定字符

s

把多个相同的输出字符缩成一个

以下实例将变量 $string 中的所有小写字母转化为大写字母:

示例:

#!/usr/bin/perl

$string = 'welcome to runoob site.';

$string =~ tr/a-z/A-Z/;

print "$string\n";

更多示例:(会用会很好用^</>^)

$string =~ tr/\d/ /c;     # 把所有非数字字符替换为空格

$string =~ tr/\t //d;     # 删除tab和空格

$string =~ tr/0-9/ /cs    # 把数字间的其它字符替换为一个空格。

更多正则表达式规则

表达式

描述

.

匹配除换行符以外的所有字符

x?

匹配 0 次或一次 x 字符串

x*

匹配 0 次或多次 x 字符串,但匹配可能的最少次数

x+

匹配 1 次或多次 x 字符串,但匹配可能的最少次数

.*

匹配 0 次或多次的任何字符

.+

匹配 1 次或多次的任何字符

{m}

匹配刚好是 m 的指定字符串

{m,n}

匹配在 m 以上 n 以下 的指定字符串

{m,}

匹配 m 以上 的指定字符串

[]

匹配符合 [] 内的字符

[^]

匹配不符合 [] 内的字符

[0-9]

匹配所有数字字符

[a-z]

匹配所有小写字母字符

[^0-9]

匹配所有非数字字符

[^a-z]

匹配所有非小写字母字符

^

匹配字符开头的字符

$

匹配字符结尾的字符

\d

匹配一个数字的字符, [0-9] 语法一样

\d+

匹配多个数字字符串, [0-9]+ 语法一样

\D

非数字,其他同 \d

\D+

非数字,其他同 \d+

\w

英文字母或数字的字符串, [a-zA-Z0-9_] 语法一样

\w+

[a-zA-Z0-9_]+ 语法一样

\W

非英文字母或数字的字符串, [^a-zA-Z0-9_] 语法一样

\W+

[^a-zA-Z0-9_]+ 语法一样

\s

空格, [\n\t\r\f] 语法一样

\s+

[\n\t\r\f]+ 一样

\S

非空格, [^\n\t\r\f] 语法一样

\S+

[^\n\t\r\f]+ 语法一样

\b

匹配以英文字母,数字为边界的字符串

\B

匹配不以英文字母,数值为边界的字符串

a|b|c

匹配符合a字符 或是b字符 或是c字符 的字符串

(abc)

匹配含有 abc 的字符串 (pattern) () 这个符号会记住所找寻到的字符串,是一个很实用的语法.第一个 () 内所找到的字符串变成 $1 这个变量或是 \1 变量,第二个 () 内所找到的字符串变成 $2 这个变量或是 \2 变量,以此类推下去.

/pattern/i

i 这个参数表示忽略英文大小写,也就是在匹配字符串的时候,不考虑英文的大小写问题. \ 如果要在 pattern 模式中找寻一个特殊字符, "*",则要在这个字符前加上 \ 符号,这样才会让特殊字符失效

反向引用

表达式:

(.)(..)\1\2\1

(.):任意一个字符

(..)任意两个字符

\1:表示第一个任意字符,即和(.)相同

\2:表示第二个任意字符,即和(..)相同

\1:表示第一个任意字符,即和(.)相同

[\t\n\r\f]=\s      空格

[^\s]=\S          非空格

[\d\D]             任意字符(包括换行符\n

捕获变量()

捕获变量使用$1/$2/$3…等特殊变量

$_="hello there,neighbor";

if(/\s(\w+),/){

      print $1;#-->小括号捕获到的变量,$1为特殊变量,一般有几个小括号就有几个$

}

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

  print "$1 $2 $3\n";#-->捕获到的三个变量

}

只分组不捕获(?:)

小括号只用于分组不用于捕获时:(?:

示例:

$_="hello there,neighbor";

if(/(?:\S+) (\S+), (\S+)/){

      print "$1 $2 $3\n";#-->现在$1=there;$2=neighbor,$3为未定义

}

捕获变量命名(?<>)

捕获变量命名(?<user_name>),用户命名在一个特殊哈希%+

$_="hello there,neighbor";

if(/(?:\S+) (?<name1>\S+), (?<name2>\S+)/){

      print "$+{name1},$+{name2}\n";

}#-->自定义命名的变量存在特殊哈希%+中

反向引用\g<>或\k<>

my $names="fred gates and wilma gates";

if($names=~/(?<last_name>\w+) and \w+ \g<last_name>/){

      print "$+{last_name}\n";

}

表达式文本可用符号

符号   含义

\U    将匹配到的字符串所有字母变为大写

\L    将匹配到的字符串所有字母变为小写

\E    结束\U\L的作用范围

\u    将匹配到的字符串的第一个字母变为大写

\l    将匹配到的字符串的第一个字母变为小写

\u\L  匹配到的字符串的第一个字母为大写,其余字母为小写

应用

省略匹配变量

在if条件中可以使用简化匹配格式,省略上文中的$_变量

if(/^\s*\//){cmd;}

表示:上文中变量$_是否可以匹配上表达式’^\s*\/

模块

localtime模块

示例:

$time = localtime();

print "\$time: $time\n";

结果:

$time: Thu Aug  1 03:12:14 2024

此处,不能直接使用print localtime()来输出时间,会得不到上结果

scalar(localtime)

示例:

perl -e 'print scalar(localtime),"\n"'

结果

Tue Aug 13 23:44:40 2024

时间格式化输出

localtime函数,根据它所在的上下文,可以用两种完全不同的方法来运行。在标量上下文中,localtime函数返回一个格式化很好的当前时间字符串。例如,print scalar (localtime)这个代码,它输出的结果将类似于Thu Sep 16 23:00:06 1999。在列表上下文中,localtime将返回能够描述当前时间的一个元素列表:

my($sec,$min,$hour,$mday,$mon,$year_off,$wday,$yday,$isdat) = localtime;

字段   值

$sec    秒,0 ~ 59

$min    分,0 ~ 59

$hour    时,0 ~ 23

$mday    月份中的日期, 1 ~ 2 8、2 9、3 0或3 1

$mon     年份中的月份, 0 ~ 11(这里请特别要小心)

$year_off   1900年以来的年份。将1900加上这个数字,得出正确的4位数年份

$wday    星期几,0 ~ 6

$yday    一年中的第几天,0 ~ 364或365

$isdst   如果夏令时有效,则为真

示例:

my  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = (localtime);

($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = (

    sprintf("%02d", $sec),

    sprintf("%02d", $min),

    sprintf("%02d", $hour),

    sprintf("%02d", $mday),

    sprintf("%02d", $mon + 1),

    sprintf("%04d", $year + 1900),

    sprintf("%00d", $wday + 1),

    sprintf("%03d", $yday + 1),

    $isdst

);

print "$isdst-$yday-$wday $year-$mon-$mday $hour:$min:$sec\n";

模块stat

定义

案例

stat函数获取文件的元数据信息,它们都会发起stat系统调用,stat函数返回共13项属性信息,这13项属性先后顺序分别是

use 5.010;

$filename=$ARGV[0]; # 第一个参数,这里使用一个file

my @arr = ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,

           $atime,$mtime,$ctime,$blksize,$blocks)

        = stat($filename);

say '$dev     :',$arr[0];

say '$inode   :',$arr[1];

say '$mode    :',$arr[2];

say '$nlink   :',$arr[3];

say '$uid     :',$arr[4];

say '$gid     :',$arr[5];

say '$rdev    :',$arr[6];

say '$size    :',$arr[7];

say '$atime   :',$arr[8];

say '$mtime   :',$arr[9];

say '$ctime   :',$arr[10];

say '$blksize :',$arr[11];

say '$blocks  :',$arr[12];

结果是:

$dev     :2050

$inode   :67326520

$mode    :33188

$nlink   :1

$uid     :0

$gid     :0

$rdev    :0

$size    :12

$atime   :1533544992

$mtime   :1533426824

$ctime   :1533426824

$blksize :4096

$blocks  :8

属性

含义

dev

文件所属文件系统的设备ID

inode

文件inode号

mode

文件类型和文件权限(两者都是数值表示)

nlink

文件硬链接数

uid

文件所有者的uid

gid

文件所有者的gid

rdev

文件的设备ID(只对特殊文件有效,即设备文件)

size

文件大小,单位字节

atime

文件atime的时间戳(从1970-01-01开始计算的秒数)

mtime

文件mtime的时间戳(1970-01-01开始计算的秒数)

ctime

文件ctime的时间戳(从1970-01-01开始计算的秒数)

blksize

文件所属文件系统的block大小

blocks

文件占用block数量(块大小一般是512字节,可通过stat -c "%B"命令获取块大小)

需要注意的是,$mode返回的是文件类型和文件权限的结合体,且文件权限并非直接的8进制权限值,要计算出Unix系统中直观的权限数值(如0755、0644),需要和0777做位与运算。

模块File::Spec

示例

### sub get_path_dir_name ###

sub get_path_dir_name{

    my $file = shift @_;  # 此处不要只用@_,否则my $file会为1,即@_的元素个数1

    print "\n1:$file 1:@_\n";

    my $file_abs = File::Spec->rel2abs($file);

    print "\n2:$file_abs\n";

    my (undef, $path_name, $folder_name) = File::Spec->splitpath($file_abs);  #此处返回的第一个参数可以不用关注,使用undef

    print "\n3:undef $path_name $folder_name\n";

    return ($folder_name,$path_name);

} # endof subroutine get_path_dir_name

my $file = $ARGV[0];  # 命令行中第一个参数为$ARGV[0],下标从0开始,$0表示脚本名

my ($folder_name,$path_name) = &get_path_dir_name($file);

print " (\$folder_name,\$path_name) = ($folder_name,$path_name) ";

print "\n";

执行:

~/perl_tra/sign_reference.pl /proj/sbio_redang_dft2/weifexie/sbiodft_krn1usb4HC0HC1_MTO_0416/SCAN_ATPG/sata_fch_usb4_container_atpg_sim/Krackan_1/usb4_sc0_t/containe

结果:

1:/proj/sbio_redang_dft2/weifexie/sbiodft_krn1usb4HC0HC1_MTO_0416/SCAN_ATPG/sata_fch_usb4_container_atpg_sim/Krackan_1/usb4_sc0_t/containe 1:

2:/proj/sbio_redang_dft2/weifexie/sbiodft_krn1usb4HC0HC1_MTO_0416/SCAN_ATPG/sata_fch_usb4_container_atpg_sim/Krackan_1/usb4_sc0_t/containe

3:undef /proj/sbio_redang_dft2/weifexie/sbiodft_krn1usb4HC0HC1_MTO_0416/SCAN_ATPG/sata_fch_usb4_container_atpg_sim/Krackan_1/usb4_sc0_t/ containe

 ($folder_name,$path_name) = (containe,/proj/sbio_redang_dft2/weifexie/sbiodft_krn1usb4HC0HC1_MTO_0416/SCAN_ATPG/sata_fch_usb4_container_atpg_sim/Krackan_1/usb4_sc0_t/)

在perl脚本中使用shell的命令

system “shell command argument …”

辨析print、say、sprintf、printf

可以查看perl用户手册

perldoc -f print
perldoc -f printf
perldoc -f sprintf

print

print、printf和say都可以输出信息。print和say类似,print不自带换行符,say自带换行符,但要使用say,必须写use语句use 5.010;,printf像C语言的printf一样,可以定制输出格式。

perl中有上下文的概念,这几个输出操作也同样有上下文环境:列表上下文

@arr=qw(hello world);

print "hello world","\n";

print "hello world\n"; 

print @arr;            # 输出helloworld(没空格)

print "@arr";          # 输出hello world(有空格)

say

use 5.010;

say "hello world!";  # 自带换行符

print/say可以以函数格式(print(args)/say(args))进行输出,这时候有个陷阱需要注意:

print(3+4)*4;

这个返回7,而不是28。这是怎么计算的?

Perl中很多时候是可以省略括号的,这往往让我们忘记括号的归属。而Perl中又有上下文的概念,在不同上下文执行同一个操作的结果是不一样的。在这里:

  • print后内容不加括号的时候,它需求的参数是一个列表上下文,它后面的所有内容都会被print输出
  • print后内容加括号的时候,它只会输出括号中的内容

所以,上面的语句等价于

(print(3+4))*4;

它先执行print(7),然后拿到print的返回值1,将其乘以4,由于没有赋值给其它变量,所以这个乘法的结果被丢弃。

如果将上面赋值给一个变量;

$num = print(3+4)*4;

该处$num的值就是4.

printf

常用:

printf FORMAT, LIST
printf FILEHANDLE FORMAT, LIST

不常用(主要是因为隐含的细节,会导致阅读上的障碍吧):

printf FILEHANDLE

sprintf

用于调整需打印的文本格式、变量格式

命令格式,只有一种:

sprintf FORMAT, LIST

区别

command     description

print       打印信息,可以输出到文件里

printf      可以整理信息的格式,可以输出到文件里。与sprintf类似,区别是可以打印

sprintf     可以整理信息的格式。与printf类似,区别是仅仅用于字符串的格式化,没有任何print效果

比如:

$result = sprintf("%08d",$number);让$number有8个前导零。

$rounded = sprintf("%.3f",$number);

让小数点后有3位数字。

sprintf允许的如下常用的转换:

%%           百分号

%c           把给定的数字转化为字符

%s           字符串

%d           带符号整数,十进制

%u           无符号整数,十进制

%o           无符号整数,八进制

%x           无符号整数,十六进制

%e           浮点数,科学计算法

%f           浮点数,用于固定十进制计数

%g           浮点数,包括%e和%f

ARGV说明

@ARGV数组

这个数组包含了传递给脚本的所有额外参数

perl命令行的参数列表放进数组ARGV(@ARGV)中。既然是数组,就可以访问($ARGV[n])、遍历,甚至修改数组元素ARGV数组索引从0开始计算,索引0位从脚本名(perl程序名)之后的参数开始计算,即使这个参数是perl的选项默认,这些命令行参数是perl程序的数据输入源,也就是perl会依次将它们当作文件进行读取

参数是有序的,读取的时候也是有序的

需要区分ARGV变量和ARGV数组:

$ARGV表示命令行参数代表的文件列表中,钻石操作符正在读取的文件名,符号<>内读入的是文件句柄,没有内容时默认是ARGV句柄,ARGV句柄指向@ARGV的各个元素,

@ARGV表示命令行参数数组

$ARGV[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的内容打印出来。

perl用来解析@ARGV的模块

Getopt::StdGetopt::Long

Getopt::Std是Perl的一个核心模块,提供了简单的接口来解析单字符选项

ARGV数组的元素可以通过索引访问,索引从0开始,$ARGV[0]、$ARGV[1]…

Ⅰ、对于需要支持长选项或者更复杂选项的场景,Getopt::Long模块是更好的选择

示例:

#!/usr/bin/perl

use strict;

use warnings;

use Getopt::Long;

my $verbose;

my $output_file;

GetOptions(

    'verbose'      => \$verbose,

    'output=s'    => \$output_file,

);

if ($verbose) {

    print "Verbose mode enabled\n";

}

if ($output_file) {

    print "Output will be saved to $output_file\n";

}

Ⅱ、需要实现更复杂的逻辑,比如参数的默认值互斥选项参数的重复

示例:

#!/usr/bin/perl

use strict;

use warnings;

use Getopt::Long;

my $input_file = “./input_file.txt”;

my %opts;

GetOptions(

    'help|?'       => sub { usage() },

    'config=s'     => \$opts{config},

    'verbose+'     => \$opts{verbose},

'port=i'       => \$opts{port},

‘debug’       => \$debug,

‘default’      =>

{‘input_file=s’=> ‘./input_file.txt’

}

) or die “Error in command line arguments”;

sub usage {

    die "Usage: $0 [--config FILE] [--verbose] [--port PORT]\n";

}

Ⅲ、在解析参数后,验证参数的有效性并处理错误是必不可少的步骤

if ($opts{port} && $opts{port} !~ /^\d+$/) {

    die "Invalid port number: $opts{port}\n";

}

关于Getoptions函数的补充说明

接受一个哈希表作为参数,其中键是选项的名称,值是一个引用,指向存储选项值的变量。

例如,"debug" => \$debug 表示将 --debug 选项的值存储在 $debug 变量中。如果选项后面没有值,则变量将被设置为 1。

GetOptions 函数还可以接受一些选项,用于指定默认值、验证选项值等。例如,可以使用 default 选项指定选项的默认值。

在Perl中,你可以使用标准模块Getopt::Long来解析命令行选项(Command Line Options)。Getopt::Long模块允许你定义命令行选项以及它们的值,并且还可以处理各种类型的选项,如标志选项(flag options)和带有参数的选项。

以下是一个简单的示例,展示了如何在Perl中使用Getopt::Long模块来处理命令行选项:

#!/usr/bin/perl

use strict;

use warnings;

use Getopt::Long;

my $input_file;

my $output_file;

my $verbose;

# 定义命令行选项以及它们的值

GetOptions(

    "input=s"   => \$input_file,   # 带有参数的选项,使用"s"表示字符串

    "output=s"  => \$output_file,  # 带有参数的选项,使用"s"表示字符串

    "verbose"   => \$verbose,      # 标志选项,没有参数

) or die "Error in command line arguments.\n";

# 检查选项是否正确解析

if ($verbose) {

    print "Verbose mode is enabled.\n";

}

if ($input_file) {

    print "Input file: $input_file\n";

}

if ($output_file) {

    print "Output file: $output_file\n";

}

假设以上脚本保存为script.pl。你可以通过在命令行中输入类似以下的命令来运行它:

perl script.pl --input input.txt --output output.txt --verbose

这个脚本将会解析命令行选项,并根据传递的参数输出结果。在上面的示例中,我们定义了三个选项:–input、–output 和 --verbose。其中,–input和–output是带有参数的选项,而–verbose是一个标志选项(没有参数,只需要出现与否来表示是否启用)。

Getopt::Long模块将在运行脚本时解析命令行参数,并将对应选项的值赋给我们定义的变量。注意,如果用户提供了无效的选项或选项值,Getopt::Long会返回0,此时我们使用or die语句来输出错误信息并终止脚本的执行。

总之,Getopt::Long模块为Perl脚本提供了一个方便且灵活的方式来处理命令行选项。

perl模块 Getopt::Long解析参数

Getopt::Long模块是用于解析命令行参数的perl模块

选项解析

其他用法

使用options调用subroutines

多命名选项

捆绑选项

- 和

GetoptLongConfigure

## option variables with default value

my $verbose = "";

my $nda = "";

my $more = 0;

my $value = "";

my @libs = ();

my %defines = ();

## parse options from @ARGV

GetOptions(

    'verbose' => \$verbose,

    'nda!' => \$nda,

    'more+' => \$more,

    'tag=s' => \$tag,

    'value:s' => \$value,

    'libs=i' => \@libs, ## 'libs=i@' => \$libs,

    'define=s' => \%defines, ## 'define=s%' => \$defines,

) or die $!;

选项解析

verbose,只有单独的一个选项,不接受任何参数。在命令行用--verbose来触发,触发后$verbose被设置为1,次用法常作为一个开关选项使用。

nda!,该选项在nda后加一个!,表示可以接受--nda和--nonda两个选项,对应的将$nda设置为1和0,如果触发该选项,$nda值为""(即空值),可以用perl内置函数length检测$nda。

more+该选项的+表示在参数列表每出现一次--more,对应的变量$more自加1。

tag=s该选项必须接受一个string参数,=表明必须要接受一个参数,s表明参数为任意字符串,也可用if指明参数为整数或浮点数

value:s与tag=s的唯一区别是:,表明不是必须接受一个参数,可以--value形式调用,s默认赋值为""i/f默认赋值为0

|:    "help|h|?"        => \my $help,

表示或者。

libs=i指定一个数组引用@libs,表明可以多次使用"--libs <lib>"获取多个值并存到数组中,也可以使用另一种形式'libs=i@' => \$libs,如果要使用"--libs <lib1> <lib2> <lib3>"这种参数调用形式,在GetOptions()中使用'libs=i{3}' => \@libs指定每次传入3个值。可以试试'libs=i{1,}' => \@libs。

define=s指定一个hash引用%defines,用--define os=linux传入一个hash参数。其他特点同上一个段落。

其他用法

使用options调用subroutines

my $verbose = "";

GetOptions(

    'set' => \&handle,

) or die $!;

sub handle {

    $verbose = 100;

    print "options \'--set\' set verbose $verbose\n";

}

多命名选项

GetOptions('length|height' => \$length);

1

捆绑选项

ex: ls -al

## 用法1

use Getopt::Long;

Getopt::Long::Configure("bundling"); ## **配置选项**

my $long = "";

my $all = "";

my $al = "";

GetOptions(

    'long|l' => \$long, # 此处必须显式的指定'l'为'long'的aliase

    'all|a' => \$all, # 此处必须显式的指定'a'为'all'的aliase

    'al' => \$al,

) or die $!;

## 现在命令行可使用 '-al'选项,同时设置$long/$all为1.**single dash**

## 使用'--al'选项设置$al为1.**double dash**

## 用法2

use Getopt::Long;

Getopt::Long::Configure("bundling_override"); ## **配置选项**

my $long = "";

my $all = "";

my $al = "";

GetOptions(

    'long|l' => \$long, # 此处必须显式的指定'l'为'long'的aliase

    'all|a' => \$all, # 此处必须显式的指定'a'为'all'的aliase

    'al' => \$al,

) or die $!;

## 现在不可以使用 '-al'选项设置$long/$all,'-al'和'--al'的作用是一样;

## 不过仍然能使用bundling,因为有长选项'--al'存在,所以捆绑选项'-al'被override;

## 如果没有长选项'--al','-al'仍然与方法1中的作用一样。

## 在用法一和用法二中,如果'long|l=i' => \$long,'all|a=i' => \$all,

## 即$long/$all都需要一个整数作为参数,那么可使用'-l11a22'实现'length=11''all=22'的效果

#用法3

use Getopt::Long;

Getopt::Long::Configure("bundling_values");

...

GetOptions(

    ...

) or die $!;

## 只有'-l11'或者'-a22'可以使用,'-l11a22'和'-al'等方式都不能用

## 用法4

use Getopt::Long;

Getopt::Long::Configure("bundling", "ignorecase_always");

...

## 当使用Configure的'bundling'配置时,短名称如'-a/-l'都是大小写敏感,

## 而长名称对大小写不敏感,所以使用"ignorecase_alwasy"选项设置为全部大小写不敏感。

‘-’ 和 ‘<>’

通常在命令行不识别单个的single-dash‘-’,可以使用如下方法捕获single-dash为参数选项。

GetOptions(

    '' => \$single,

) or die $!;

使用GetOptions解析命令行时,当遇到无法识别的字符或者本来不是命令行选项的选项,可以用<>捕获。

## '<>'只能指向函数引用,可以通过函数做很多有意义的事

GetOptions(

    '<>' => \&handle,

) or die ;

sub handle

{

    my $catch = shift;

    print "catch: $catch\n";

}

Getopt::Long::Configure()

指定Getoptions的各项特性

使用方法

## 方式1

use Getopt::Long qw(:config bundling no_ignore_case); ## 参数列表

## 方式2

use Getopt::Long;

Getopt::Long::Configure("bundling", "no_ignore_case"); ## 参数列表

default

bundling(default: disable)

可使用捆绑选项

bundling_override(default: disable)

用长选项重写bundling中出现的短选项。

ignore_case(default: enable)

默认大小写不敏感,对bundling状态的-<single-character>选项无效;

no_ignore_case该选项禁用,同时也会禁用ignore_case_always

ignore_case_always(default: disable)

针对bundling状态的大小写忽略

pass_through (default: disable)

对于GetOptions()中无法识别或者不需要识别或者无效的选项,都不会返回错误。

可以用于多级程序调用时的参数传递。因为GetOptions()会将识别的选项从@ARGV中取出,所以剩余的内容就可以继续传递到下一级程序。

debug(default: disable)

查看Getopt::Long模块处理参数时的debug信息

$#ARGV

表示命令行中参数的个数-1,表示最后一个参数的索引号

最后一个参数:$ARGV[$#ARGV]、或者$ARGV[-1]

$scalar = @ARGV

将命令参数列表赋值给一个标量,该标量表示参数个数

$0 – 表示脚本名称

注意:包括从输入开始到脚本名结束的全部字符,包括path,如~/perl.pl arg0 arg1,$0为~/perl.plss

注意:GetOptions后,@ARGV里面将没有参数了,均已挨个取出分析

return和print区别

print即立马打印内容到终端;

return是将结果作为返回的内容,对于返回的内容处理由其他的命令执行

作为函数返回结果的命令,如

sub subroutine_name {
body of the subroutine
}

&subroutine_name(@_)

传参:@_ 接收

return 返回值

示例

sub NCP_SPLIT_YES_pat_gen_sub_0_new_ncp_strategy{

my $here = << 'PAT_SAVE';

    // Begin ATPG_NCP_SPLIT = YES pattern generation

    set ext_pat_list ""

    foreach current_ncp "$ncp_list" {

        puts "+++---current pattern generation for NCP of $current_ncp"

        set ext_pat_list "$ext_pat_list $current_ncp "

        reset_state

        reset_au_faults

        // reset_au but not re-build faults list to let pattern gen efficient

        //delete_faults -all

        //read_faults $env(rpt_dir)/${mode}_before_patgen_faults.txt.gz

        set_capture_procedures off -all

        set_capture_procedures on $current_ncp

PAT_SAVE

return($here) ;

}   #End of NCP_SPLIT_YES_pat_gen_sub_0_new_ncp_strategy

return命令是将内容作为子程序的结果返回

while和foreach读取文件内容

while:读取到空行结束,读取下一行

foreach:读取到空行,将空行作为$_去执行结构体,知道读取到文件结尾结束

perl中常用命令

perl中很多基本语法在前文已总结,对于perl中常用的命令只是零星的给出,此处做较全面的总结。

grep

syntax:

1 grep BLOCK LIST

2 grep EXPR, LIST

BLOCK表示一个code块,通常用{}表示;EXPR表示一个表达式,通常是正则表达式。原文说EXPR可是任何东西,包括一个或多个变量,操作符,文字,函数,或子函数调用。

LIST是要匹配的列表。

grep对列表里的每个元素进行BLOCK或EXPR匹配,它遍历列表,并临时设置元素为$_。在列表上下文里,grep返回匹配命中的所有元素,结果也是个列表。在标量上下文里,grep返回匹配命中的元素个数。

例子1:

将数组的每个元素的空格用_代替

my @arr=("Head PMA1","Head PMA2","Head PMA3","Head PMA4","Head PMA5","Head PMA6");

my @arr1=grep $_=~s/\s/_/g,@arr;

#元素个数

my $arr1_Lenght=@arr1;

print "@arr1:\n$arr1_Lenght";

输出结果
Head_PMA1 Head_PMA2 Head_PMA3 Head_PMA4 Head_PMA5 Head_PMA6:
6

例子2:去除哈希所有键的_

my %IOtypes = ("D_O", 0, "A_O", 1, "D_I", 2, "A_I", 3);

#去除哈希所有键的_

foreach my $Io (grep $_=~s/_//g, keys %IOtypes )

{

   print "$Io\t";

}

输出结果

DO      AI      AO      DI

Grep vs. loops
open FILE "<myfile" or die "Can't open myfile: $!";
print grep /terrorism|nuclear/i, <FILE>;;

这里打开一个文件myfile,然后查找包含terrorism或nuclear的行。<FILE>;返回一个列表,它包含了文件的完整内容。
可能你已发现,如果文件很大的话,这种方式很耗费内存,因为文件的所有内容都拷贝到内存里了。
代替的方式是使用loop(循环)来完成:
while ($line = <FILE>;) {
if ($line =~ /terrorism|nuclear/i) { print $line }
}
上述code显示,loop可以完成grep能做的任何事情。那为什么还要用grep呢?答案是grep更具perl风格,而loop是C风格的。
更好的解释是:(1)grep让读者更显然的知道,你在从列表里选择某元素;(2)grep比loop简洁。

符号辨识

!!$var

defined$var

判断变量$var是否有初始化值,my $var;表示没有初始化值。my $var = “”;表示有初始化。

exists $var

用于判断hash、array(ref)中的元素是否存在,function函数是否定义。exists argument is a HASH or ARRAY element,exists操作的对象需要是一个hash或者array元素。

判断一个hash中的键是否存在,键存在但有可能是undef。在hash中,当检验一个元素值是否被定义赋值是用defined,当检验一个key在hash中是否存在时,用exists(即使该键下的值不存在)

print "Exists\n" if exists $hash{$key};  # 这个exists可以避免了键$hash{$key}不存在返回undef造成程序报错的情况

print "Defined\n" if defined $hash{$key};

print "True\n" if $hash{$key};

这里:

$hash{$key}是值,键的获取方式是my $key = keys %hash;

$variable

多维哈希

定义

一维hash的赋值方式多种多样,而多维hash使用最基本的单点赋值方式赋值

my %my_hash;

my $sig1 = "amod_bmod_awsize";

my $sig2 = "bmod_amod_bresp";

$my_hash{$sig1}{name}  = "amod_bmod_awsize";

$my_hash{$sig1}{width} = 8;

$my_hash{$sig1}{link}{src} = "amod";

$my_hash{$sig1}{link}{dst} = "bmod";

$my_hash{$sig2}{name}  = "bmod_amod_bresp";

$my_hash{$sig2}{width} = 2;

$my_hash{$sig2}{link}{src} = "bmod";

$my_hash{$sig2}{link}{dst} = "amod";

$my_hash{$sig2}{sel}{0} = 0;

$my_hash{$sig2}{sel}{2} = 2;

$my_hash{$sig2}{sel}{10} = 10;

多维hash一样可以跟一维一样用胖箭头赋值

多维hash的某一个key可能指向某一个值,也可能指向一个hash,例如上式中$my_hash{$sig2}指向一个多维hash,$my_hash{$sig2}{name}指向一个值。指向hash的键是一个引用(地址),指向其值(hash)。

注意:而一个key是不能即指向一个值又指向一个其他的东西。

$my_hash{$sig} = "awsize";

$my_hash{$sig}{src} = "a";

$my_hash{$sig}{dst} = "b";

上写法不对,键$my_hash{$sig}的值为“awsize”后就不能再作为键,来指向hash(src=>a,dst=>b)

赋值时,$my_hash{$sig}{dst} = "b" 和  $my_hash{$sig}{"dst"} = "b"是一样的,当然%hash_A = ("key1" => value1, "key2" => value2) 和 %hash_A = (key1 => value1, key2 => value2) 也是一样的,keyx会自动被引号引起来。

打印

一维hash一般直接print %hash就够用了,而对于嵌套的多维数组呢,可以借助一个库来实现清晰的打印:

use Data::Dumper;

my %my_hash;

........

print Dumper(\%my_hash);

%my_hash:

$VAR1 = {

          'bmod_amod_bresp' => {

                                 'name' => 'bmod_amod_bresp',

                                 'width' => 2,

                                 'sel' => {

                                            '10' => 10,

                                            '2' => 2,

                                            '0' => 0

                                          },

                                 'link' => {

                                             'dst' => 'amod',

                                             'src' => 'bmod'

                                           }

                               },

          'amod_bmod_awsize' => {

                                  'link' => {

                                              'dst' => 'bmod',

                                              'src' => 'amod'

                                            },

                                  'width' => 8,

                                  'name' => 'amod_bmod_awsize'

                                }

        };

上打印的格式是默认格式,可以使用下脚本对打印经行控制

#!/usr/bin/perl -w

use strict;

use warnings;

use Data::Dumper;

sub display_hash{

      my $obj   = shift @_;

      my $tab_n = shift @_;

      my $tab   = "";

      my @re;

     

      $tab_n = 0 unless $tab_n;

     

      $tab = " " x $tab_n;

      my %hash = %$obj;

      for my $key(sort {$a cmp $b} keys %hash){

            $str = $tab."$key";

            if(ref $hash{$key} eq "HASH"){

                  #$str .= "\n";

                  push(@re, $str);

                  @re = (@re, &display_hash(\%{$hash{$key}}, $tab_n+4));

            } else {

                  $str .= " => $hash{$key}";

                  push(@re, $str);

            }

      }

      return @re;

}

sub display_list{

      my @list   = @_;

      for my $obj (@list){

            print "$obj\n";

      }

}

&display_list(&display_hash(\%my_hash));   # 从右往左计算的优先级

执行的结果:

amod_bmod_awsize

    link

        dst => bmod

        src => amod

    name => amod_bmod_awsize

    width => 8

bmod_amod_bresp

    link

        dst => amod

        src => bmod

    name => bmod_amod_bresp

    sel

        0 => 0

        10 => 10

        2 => 2

    width => 2

删除

同一维hash一样,删除一个key会将其所指向的内容全部删除:

delete $my_hash{bmod_amod_bresp}{width};

delete $my_hash{"amod_bmod_awsize"}{name};

遍历

下层hash%{}转一下:

for my $obj0 (sort keys %my_hash){

      for my $obj1(sort keys %{$my_hash{$obj0}}){

            print "$obj1, $my_hash{$obj0}{$obj1} \n";

      }

}

结果:

link, HASH(0x190a4e0)

name, amod_bmod_awsize

width, 8

link, HASH(0x19793f8)

name, bmod_amod_bresp

sel, HASH(0x19439b8)

width, 2

引用

正常的$obj = \%my_hash引用就可以了,解引用也可直接%hash = %$obj或者不解直接用$obj->{$sig1}->{name}这样用应该也是没问题的,以下三种方式都可以:

my $hash = \%my_hash;

print "hello1, $hash->{amod_bmod_awsize}->{name} \n";

print "hello2, $hash->{amod_bmod_awsize}{name} \n";

print "hello3, ${$hash}{amod_bmod_awsize}{name} \n";

结果:

hello1, amod_bmod_awsize

hello2, amod_bmod_awsize

hello3, amod_bmod_awsize

拷贝

hash进行=直接拷贝的话,是一种深层指针拷贝,看下这个代码:

delete $my_hash{$sig1}; # no use, to long

my $sig3 = "bmod_amod_buser";

$my_hash{$sig3} = $my_hash{$sig2};

print "first, copy=====================\n";

&display_list(&display_hash(\%my_hash));

print "\nfirst, delete====================\n";

delete $my_hash{bmod_amod_bresp}{width};

&display_list(&display_hash(\%my_hash));

结果:

first, copy=====================

bmod_amod_bresp

    link

        dst => amod

        src => bmod

    name => bmod_amod_bresp

    sel

        0 => 0

        10 => 10

        2 => 2

    width => 2

bmod_amod_buser

    link

        dst => amod

        src => bmod

    name => bmod_amod_bresp

    sel

        0 => 0

        10 => 10

        2 => 2

    width => 2

first, delete====================

bmod_amod_bresp

    link

        dst => amod

        src => bmod

    name => bmod_amod_bresp

    sel

        0 => 0

        10 => 10

        2 => 2

bmod_amod_buser

    link

        dst => amod

        src => bmod

    name => bmod_amod_bresp

    sel

        0 => 0

        10 => 10

        2 => 2

可以发现,拷贝是吧全部信息都拷过去了,但是$sig2 width被删除时,$sig3中对应的信息也被删除了。因此需要深度复制拷贝的话,请使用:

use Clone 'clone';

ref函数

perl有引用的概念:一组数据实际上是另一组数据的引用。这些引用称为指针,第一组数据中存放的是第二组数据的头地址。引用的方式被用得相当普遍,特别是在面向对象的模块、函数的参数传递等常见。但perl对每个引用都是以一个普通的变量来定义的,有时候,如果数据的架构比较复杂,我们可能会困惑于某个变量所指向的地址的实际内容是什么?perl的ref函数就可以帮助我们。

说明

从perl自带的帮助说明可以了解相关的用法:

引用

$ perldoc -tf ref

ref EXPR

ref     Returns a non-empty string if EXPR is a reference, the empty

        string otherwise. If EXPR is not specified, $_ will be used. The

        value returned depends on the type of thing the reference is a

        reference to. Builtin types include:

            SCALAR

            ARRAY

            HASH

            CODE

            REF

            GLOB

            LVALUE

        If the referenced object has been blessed into a package, then

        that package name is returned instead. You can think of "ref" as

        a "typeof" operator.

            if (ref($r) eq "HASH") {

                print "r is a reference to a hash./n";

            }

            unless (ref($r)) {

                print "r is not a reference at all./n";

            }

举例

简单来说,就是如果一个变量是个引用,那ref就可以返回一个表示其实际引用对象的描述性字符串,否则就会返回空值。如果没有指定ref函数的参数,默认对$_变量操作。如果被引用的对象已经被打包,则会返回该包的名称,类似typeof操作符。

代码:

#!/usr/bin/perl -w

%hash=('Tom'=>'Male','Jerry'=>'Female');

$href=\%hash;

for my $key (keys %$href) {

  print $key." => ".$href->{$key};

  print "\n";

}

if ( ref($href) eq "HASH" ) {

  print "href is a reference to a hash./n";

}

unless ( ref($href) ) {

  print "href is not a reference at all./n";

}

print "href is ",ref($href),"./n";

输出结果:

执行

$ perl testref.pl

结果:

Jerry => Female

Tom => Male

href is a reference to a hash.

href is HASH.

示例:(%my_hash已初始化)

my %my_hash;

my $sig1 = "amod_bmod_awsize";

my $sig2 = "bmod_amod_bresp";

$my_hash{$sig1}{name}  = "amod_bmod_awsize";

$my_hash{$sig1}{width} = 8;

$my_hash{$sig1}{link}{src} = "amod";

$my_hash{$sig1}{link}{dst} = "bmod";

$my_hash{$sig2}{name}  = "bmod_amod_bresp";

$my_hash{$sig2}{width} = 2;

$my_hash{$sig2}{link}{src} = "bmod";

$my_hash{$sig2}{link}{dst} = "amod";

$my_hash{$sig2}{sel}{0} = 0;

$my_hash{$sig2}{sel}{2} = 2;

$my_hash{$sig2}{sel}{10} = 10;

1 print "ref function returns 'HASH if EXPR is hash'\n"if (ref %my_hash);   # ref %hash返回值为空,即没有返回值

2 print "ref %my_hash:",ref %my_hash,"\n";                 # 同上,为空

3 print "ref \\%my_hash:",\%my_hash,ref \%my_hash,"\n";     # ref \%my_hash 返回值HASH,即\%my_hash表示引用地址

4 print "$my_hash{$sig1}:",ref $my_hash{$sig1},"\n";       # $my_hash{$sig1}是引用,也是哈希my_hash的键,值为另一个哈希

5 print "$my_hash{$sig1}{link}:",ref $my_hash{$sig1}{link},"\n";  # $my_hash{$sig1}{link}为引用,指向一个哈希,本身是键

6 print "$my_hash{$sig1}{name}:",ref $my_hash{$sig1}{name},"\n";

解果:

1 NULL

2 ref %my_hash:

3 ref \%my_hash:HASH(0x23162f0)HASH

4 HASH(0x2187d48):HASH

5 HASH(0x23769e8):HASH

6 amod_bmod_awsize:

函数

函数的声明与定义

Perl函数声明的语法为:

sub NAME [PROTOTYPE] [ATTRIBUTE]

Perl函数定义的语法为:

sub [NAME] [PROTOTYPE] [ATTRIBUTE] BLOCK

sub(函数关键字):Perl中的子函数关键字,不可省略。

NAME(函数名字):函数名字在函数声明中是必需的,而在函数定义中则是可选的。在函数定义中如果省略函数名则表示声明了一个匿名函数,此时需要提供一个调用匿名函数的方式

PROTOTYPE(函数原型):用来定义函数出入参数的格式

ATTRIBUTE(函数属性):用来定义函数的属性

BLOCK(函数体):函数的代码体,只存在函数的定义中

函数的调用方式

Perl中函数的调用方式主要有三种:

通过函数名直接调用

这种调用方法只能调用命名函数。它的调用语法为:

NAME[(param1,param2,…)]

如果函数调用之前已经做了函数的声明或者定义,那么函数名字后面的括号是可以省略的。如果函数在调用之前没有做函数的声明或者定义,后面的括号不可省略

使用前置&号调用

这种调用方式也只能调用命名函数。它的调用语法为:

&NAME[(pamram1,param2,…)]

这种调用方式下,不论声明或者定义是否在函数调用之前,函数名后面的括号均可以省略,因为符号&明确告诉Perl解释器这是一个函数调用,Perl解释器会在所有可见的名字空间中寻找该函数,如果找不到会报运行时错误。

使用引用调用

这种调用方式既可以调用命名函数也可以调用匿名函数。调用匿名函数时需要用一个标量变量来保存对匿名函数的引用。这种方式的调用语法有以下两种:

&$subref[()]

$subref->()

&$subref

引用调用还可以调用匿名函数,但首先要保存一个匿名函数的引用。保存匿名函数的引用的语法如下:

$subref=sub BLOCK;

保存了匿名函数的引用之后,调用方式同上面命名函数的引用调用方式相同。

文件、目录类型判断

文件属性判断操作符通常与if 配合使用

文件相关

测试操作符    含义

-r    当前用户对此文件是否拥有可读权限

-w    当前用户对此文件是否拥有可写权限

-x    当前用户对此文件是否拥有可执行权限

-o    此文件所有者是否是当前用户

-f    文件是否是普通文件

-d    文件是否是目录文件

-l    文件是否是链接文件

-e    文件或目录存在

-z    判断文件内容为空,不能用于判断目录

-s    判断文件或目录存在, 返回文件或目录的大小, 单位为字节

逻辑表达式组合

  • perl 可以使用and 和 or 表示逻辑与和逻辑或的关系
  • 隐式文件句柄 _ 表示上次监测的文件, 用于提升效率

if ( -f $file and -x _ ) {

   print "文件$file 存在且可执行\n";

}

文件读写操作

文件

1.1open-close

open FILEHANDLE, EXPR

...

open(FILE,"<sim.log") or die "can't open sim.log,$!";   

#open(FILE,"<","sim.log") or die "can't open sim.log,$!";    #也可以

#open(FILE,"r","sim.log");    #不支持

while(<FILE>){    #<>为钻石操作符,按行读取文件内容

    print "$_\n";

}

close FILE;

#close;    #也可以,但不建议,容易出错

EXPR中:

<     只读(open默认方式),文件指针指向开头;不存在则报错

>     只写,文件指针指向开头;不存在则尝试创建

>>    只写,文件指针指向结尾(追加);不存在则尝试创建

+<    读写,文件指针指向开头,写多少覆盖不少;不存在则报错

+>    读写,文件大小直接截为0;不存在则尝试创建

+>>   读写,文件指针指向结尾;不存在则尝试创建

1.2读写文件

<> 文件句柄操作符,<FILEHANDLE>读取句柄指向的文件的内容,标量环境返回一行内容,数组环境返回整个文件内容。<>默认从命令行参数列表@ARGV中的文件中读取内容,@ARGV中若无元素,则从STDIN标准输入文件句柄中读取,也可使用<FILEHANDLE>手动指定句柄。

*rename string1,string2;重命名

*unlink filename1;删除文件

1.3文件位置

tell FILEHANDLE:获取文件当前位置,以字节计;

seek FILEHANDLE, POSITION, WHENCE:移动读写指针,position指定移动的字节数,whence指定移动的起点012分别表示文件开头、当前位置,结尾。

sysopen(DATA,"sim3.log",O_RDONLY) or die "can't open sim.log,$!";

#following sysopen doesn't work 只读的模式下可以添加0755么?

#sysopen(DATA2,"./sim2.log",O_WRONLY|O_CREAT,0755) or die "can't create sim2.log,$!";

open DATA2,"+>sim2.log" or die "can't open sim2.log,$!";

while(<DATA>){

    print DATA2 $_;#there is no "," between DATA2 and $_

    printf "DATA2 position:%d\n",tell DATA2;

    #finally,print moves ptr of DATA2 to the end

}

print tell DATA2,"\n";

seek DATA2,0,0;    #重定向读写指针到文件开头,否则下面的while无法执行

print tell DATA2,"\n";

while(<DATA2>){

    print "in sim2.log: $_\n";

}

1.4文件信息

-A    文件上一次被访问的时间(单位:天)

-B    是否为二进制文件

-M    文件上一次被修改的时间(单位:天)

-T    是否为文本文件

-d    为目录

-e    文件或目录名存在

-f    为普通文件

-l    为符号链接

-p    文件是命名管道(FIFO)

-s    文件或目录存在且不为0(返回字节数)

-z    文件存在,大小为0(目录恒为false),即是否为空文件,

md5加密算法

md5算法,全称是Message-Digest Algorithm 5,即信息摘要算法。

MD5是一种哈希算法,可以将任意长度的数据转换为固定长度的哈希值,通常用于验证数据完整性,即通过比对两个数据的MD5值来判断它们是否相同。文件是计算机中的一种数据存储形式,可以保存数据或程序。文件也可以通过MD5算法计算出其哈希值, MD5是一种数字指纹,而文件则是一个具体的数据或程序,md5除了应用于文件内容校验,还包括密码加密等应用场景。

例如:

在使用已知的10个文件作为源文件用来生成输出文件,为了防止在输出文件生成之后,源文件遭到修改或者破坏,可以使用md5算法得到源文件的哈希值。

md5算法有以下特点:

压缩性:任意长度的数据,算出的MD5值长度都是固定的。

容易计算:从原数据计算出MD5值很容易。

抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。

强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

示例:

use Digest::MD5 qw(md5_hex)

system “md5sum $file”;

结果:

473c42befc033ec760f6dc7181866d81 edt_saf_single_clk_func_addsmsgcxfinaltunecom/rpt/md5sum.rpt


==念念不忘,会有回响==

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weifexie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值