加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Learning Perl 6

发布时间:2020-12-16 00:37:40 所属栏目:大数据 来源:网络整理
导读:?1. 常用的Perl命令行参数 -C 这个参数编译Perl程序但不会真正运行它.由此检查所有语法错误.每次修改perl程序之后我都会立刻使用它来找到任何语法错误. -w 等同于use warning; -e 从命令参数中的’’执行脚本,而非脚本文件 -n 如果需要遍历文件或者查找固定

?1. 常用的Perl命令行参数

-C 这个参数编译Perl程序但不会真正运行它.由此检查所有语法错误.每次修改perl程序之后我都会立刻使用它来找到任何语法错误.
-w 等同于use warning;
-e 从命令参数中的’’执行脚本,而非脚本文件
-n 如果需要遍历文件或者查找固定的模式,使用-n开关隐式一行一行读取文件。 常与-e连用编写类似awk的语句。
SHELL>perl –ne ‘print;’ 1.txt #等同于while(<>){print;}
SHELL>perl –ne ‘print “$.-$_”;’ 1.txt #输出行数-内容
BEGIN{},END{}块用于在循环前或者循环后执行。例如统计文件单词数:
SHELL>perl –ne ‘END{print $t} @w=/(w+)/g; $t+=@w’ 1.txt #@是匹配的模式内容(列表上下文下,每行为一个匹配的模式内容)。$t加上@w的行数即单词数。这个还可以用于其它模式数量的查找。
-M 引用模块,等同于use
SHELL>perl –MLWP::Simple –e ‘getstore(“www.163.com”)’;
-F 设置分隔符。例如/etc/passwd是以:为分隔符的。统计不同的Shell的使用人数。
SHELL>perl -F':' –ane '$s{$F[6]}++;'&;;-e' END{print "$_:$s{$_}"for keys %s}' /etc/passwd
$/,$ 输入、输出分隔号。是从输入数据时,每一次读到到达这个符号就会停止。$/默认是’n’,所以就会一行行的读取。$是默认加到printf,print之后的字符。默认是空字符(所以print没有换行的功能)。
-l 使$=$/,并chomp时自动输入分隔号。这样在print
-i 原位编辑。就似乎对输入文件本身修改。例如实现类似sed
SHELL>perl –ipe ‘s/bphp/bPerl/’ file.txt
2. 常用的Perl特殊变量
(1). $_
默认的输入和模式搜索空间。
while(<>){…} is same as while(defined($_ = ?<>)){…}
/^something/ is same as $_ =~ /^something/
tr/a-z/A-Z/ is same as $_ =~ tr/a-z/A-Z/
chomp is same as chomp $_
其他Perl会默认使用$_的地方:
各种单目函数。
各种测试操作例如-f,-d。-t默认是STDIN
各种列表函数print unlink
各种模式匹配操作
循环
(2). $a,$b sort包的比较函数的特殊变量。在use strict ‘vars’时也不用声明就可以使用。在sort的比较块/函数使用时,不要用my $a定义它。
(3). $num 捕获的模式匹配的子模式。这些变量只读。注意/(a)(b)12/中,只有$1,$2,后面的重复使用不能算3,4。另外,这些组的序号由左括号的顺序决定。还有一组$^n由右括号的顺序决定的对等变量。
(4). $PREMATCH $` 上次成功的模式匹配之前到得字符串。
$MATCH $& 上次成功的模式匹配到得字符串
$POSTMATCH $’ 上次成功的模式匹配之后得到的字符串
$LAST_PAREN_MATCH $+ 含有上次成功的匹配模式中最后的一个括号匹配的文本。当无法确定是上一次哪个匹配成功时,这个变量很有用。
注意,上一次失败的匹配不会改变它们的结果。它们是只读变量 ,且仅对当前块有作用域。如果使用这些变量会导致所有模式匹配的性能降低。
(5). @LAST_MATCH_START @-数组保存了当前活动的动态作用域中最近成功匹配开始时得偏移量。@-[0]为整个匹配在字符串中开始处的偏移量。@-[1]为$1开始处的偏移量,以此类推。
@LAST_MATCH_END @+数组保存了当前活动的动态作用域中最近成功匹配结束处得偏移量。@+[0]为整个匹配在字符串中结束处的偏移量。@+[1]为$1结束处的偏移量,以此类推。
$#+可以得到最近有多少组成功匹配。
如果没有子模式匹配,则这些都为undef。
对$_匹配后,$&的内容和substr $_,$-[0],$+[0] - $-[0]的内容一样。如果$num定义,则$num与substr $_,$-[n],$+[n] - $-[n]一样。$+和substr $_,$-[$#-],$+[$#-] - $-[$#-]相同。可以用$#-找到正则表达式中最后一个匹配的子组。而$#+是那次匹配时正则表达式中子组的数目。其他对等:
$` substr($var,$-[0]);
$’ substr($var,$+[0]);
(6). $*将其设置为非0整数值就可以对字符串内的多行匹配。默认为undef。该变量只影响了对^$的解释。现在perl中应该用/s和/m取代他的功能。
(7). $.最后读取的文件句柄的当前行号。一行指的是遇到$/的地方。默认$/为n。关闭文件句柄会复位$.
$/ $ 输入,输出记录分隔符。将$/设置为整数,存有整数的标量时,perl会尝试读入字节的长度不是行。例如
Local $/=32768
Open my $df,$myfile or die $!;
Local $_ = <$df> #读取32768个字符。
(8). HANDLE->autoflush(expr),$OUTPUT_AUTOFLUSH,$|若该变量为非零值,就会强制进行刷新,并且当前选中的输出通道在打印(或者写到文件)之后都会进行刷新。默认为0.通常STDOUT是行缓冲,写到文件或其他是块缓冲。
$OUTPUT_FIELD_SEPARATOR,$OFS,$, 为 print 的输出域分隔符。通常 print不经任何修饰就输出它的参数,要 得到更像 awk的行为,可以将该变量设置成和 awk 的 OFS 变量一样,以指定域之间打印什么。(助记:当print语句里有“,”时会打印的东西。)
IO::Handle->output_record_separator EXPR,$OUTPUT_RECORD_SEPARATOR,$ORS,$ 为 print 的输出记录分隔符。通常 print简单地原样输出它的参数,不增加任何结尾的换行符或其他表征记录结束的字符串。要得到更像 awk的行为, 可以将该变量设同 awk 的 ORS 变量一样,以指定在 print ?的结尾输出 什么。(助记:设置 $ 而不是在 print结尾加“n”。另外,它长得和 $/ 很像,但却是你从 Perl那里拿“回”的东西。) (译注:“回”原文为单词“back”,还指代反斜杠“backslash”,起一语双关作用。)
$LIST_SEPARATOR,$" 该变量同$,类似,但应用于向双引号引起的字符串(或类似的内插字符串)中内插数组和切片值的场合。默认为一个空格。
$# ? ? ?为打印数值时的输出格式。不建议使用 $# 变量。
(9). $CHILD_ERROR$? ? ? ?由最近的管道关闭、反引号(``)命令、成功调用 wait() 和 waitpid()或者 system() 操作符返回的状态信息。它就是由 wait()系统调用返回的 16 位状态字 (或是由其他信息组合而成的类似值)。因此,子进程的退出值实际上是 ("$? >> 8"),"$? & 127" 给出了导致进程结束的信号代码(如果存在),而 "$? & 128" 会报告是否产生了内核转储。(助记:同 sh 和 ksh类似。)
在 "END" 子程序里,$? 含有即将交给 "exit()" 的值。可以在 "END"子程序 中修改 $? 以达到改变程序退出状态的效果。例如:?
END {
$? = 1 if $? == 255; ?# die would make it 255
}?
(10). $OS_ERROR,$ERRNO,$! ? ? ?如果按数值使用该变量,就会得到 "errno"变量的当前值;换句话说,如果某个系统或者库函数调用失败了,就会设置该变量。这意味着$!的值仅当 *紧接*在一个失败之后时才有意义:
? ?$EVAL_ERROR,$@ ? ? ?最近一个 eval() 运算符返回的 Perl 语法错误消息。 若 $@ 是空字符串,则最近一次 eval() 进行了正确的解析和执行( ?但是你所进行的操作可能已经按照通常的形式失败了)。 (助记:语法错误发生“在”哪里?)
(11). $PROCESS_ID,$PID,$$ 运行本脚本的 Perl 的进程号。该变量应视为只读的,不过在 fork()调用 时会被改变。(助记:和 shell 一样。) Linux 用户注意:在 Linux 下, C 函数 "getpid()" 和 "getppid()"对 不同的线程返回不同的值。为了可移植,该行为没有反映在 $$里,该变量 的值在线程间保持不变。如果你想调用底层的"getpid()",可以使用 CPAN 模块 "Linux::Pid"。
$REAL_USER_ID,$UID,$< 本进程的实际 uid。(助记:如果你用了 setuid,那么这是你原来的uid。) 可以用 POSIX::setuid() 同时改变实际 uid 和有效uid。由于改变 $< 需要 进行系统调用,在更改之后应检查 $!以发现可能产生的错误。
$EFFECTIVE_USER_ID,$EUID,$> ?本进程的有效 uid。例:
$< = $>; #set real to effective uid
($<,$>) = ($>,$<); ?# swap real and effective uid
可以用POSIX::setuid()同时改变有效uid和实际uid。更改$>后需要检查$!以发现可能产生的错误。(即如果你用了 setuid,那么这是你要变成的 uid。)?
? ? ? $REAL_GROUP_ID,$GID,$( 本进程的实际gid。如果你使用的机器支持同时属于多个组,则该变量给出的是被空格隔开的所在组列表。第一个数值是由 getgid()返回的结果,后续的内容 是 getgroups()返回的结果,其中可能有和第一个值相同的项。
然而为了设置实际 gid,赋给 $( 的必须是单个数值。因此从 $( 得到的值在没有强制为数值(例如同零相加)的情况下*不应*再赋给 $(。可以用 POSIX::setgid() 同时改变实际 gid 和有效 gid。更改 $(. 后需要检查 $! 以便发现可能出现的错误
? ? ? ? ? ?$EFFECTIVE_GROUP_ID,$EGID,$) ? ? ?本进程的有效 gid。如果你使用的机器支持同时属于多个组,则该变量给出的是被 空格隔开的所在组列表。第一个数值为 getegid()的返回值,后续的值是 getgroups()的返回值,其中可能有和第一个值相同的项。类似地,赋给 $) 的值也必须是一个空格隔开的数值列表。第一个数设置有效 ?gid,其余部分(若存在)则传给 setgroups()。要达到向 setgroups()传递空列表 的效果,只需重复一遍新设置的有效 gid;例如,要将有效 ?gid 强制为 5 并向 setgroups() 传入空列表,就要这么写:" $) = "5 ?5" "。可以用 POSIX::setgid() 同时改变有效 gid 和实际 gid ?(只用单个数值参数)。 更改 $) 后需要对 $!进行检查以便发现可能出现的错误。
? ? ? ? ? ? $<、$>、$( 和 $) 只能在支持对应的 *set[re][ug]id()* ? 例程的机器上进行设置。$( 和 $) 只能在支持 setregid() 的机器上互换。
? ? $PROGRAM_NAME,$0 ? ? ?包含当前运行程序名。在一些(注意:不是全部)操作系统下,向 $0 赋值可以改变 "ps" 程序所看到 的参数域。某些平台上你可能需要用特殊的 "ps" 选项或其他的 "ps" 才能看到 这个改变。修改 $0 作为指示当前程序状态的一种方法,要比用来隐藏你在运行的程序更有用。(助记:同 sh 和 ksh 一样。) ?注意 $0的最大长度受相关平台的限制。多数极端情况下可能被限制在原始的 $0所占据的空间之内。 ?在某些平台上可能会附加一些填充字符(例如空格)在 "ps" ?显示出的修改名 之后。有些平台上这种填充会充满原参数域,并且不受你的控制(例如Linux 2.2)。
? ? (12).$OSNAME,$^O为当前 Perl副本编译时所处的操作系统名称,在配置过程中即确定。其值同$Config{'osname'} 相同。另见 Config 及 perlrun 中说明的 -V命令行开关。
? ? (13).$ARGV 当读取<>时包含当前文件名。
?@ARGV 数组@ARGV含有脚本的命令行参数。
?$#ARGV 通常是参数数量减 1,因为$ARGV[0]是第一个参数,而*不是*程序本身的命令名称。命令名称请见$0。
? ? (14).在某个函数内,数组@_包含传递给该函数的所有参数。
? ? (15).@INC 数组@INC 包含一个路径列表,"do EXPR"、"require" 和 "use"结构都会在该列表中查找自己 所需的库文件。它的初始值由所有 -I命令行开关的参数、默认 Perl 库目录(如 /usr/local/lib/perl)和代表当前目录的“.”依次组合而成。(当使用 "-T" 或 "-t" 开启污染检查开启时则不会把“.”附加在后面。)若需要在运行时修改该变量,你应该使用 "use lib"指示符,以便能正确载入平台相关的库:
? ? use lib '/mypath/libdir/';?
? ? use SomeMod;
你还可以直接在 @INC 中放入 Perl代码,以达到在文件包含系统中插入拦截点的目的。这些拦截点可以是函数引用、数组引用或 bless 过的对象。
%INC 散列表 %INC 含有若干项,每一项都代表由 "do"、"require" 和 "use"运算符包含进来的一个文件。散列键是包含处给定的文件名(模块名已转换为路径名),散列值为找到该文件的位置。 "require"运算符用这个散列表判断某个特定文件是否已经被包含过。
? ? (16).%ENV,$ENV{expr}散列表%ENV含有当前的环境。对 "ENV" 设置值会改变后续 fork()出来的所有子进程的环境。
? ? (17).%SIG,$SIG{expr} ?散列表 %SIG 包含信号对应的处理器。例如:
sub handler { ? ? ? # 第一个参数是信号名称
my($sig) = @_;
print "Caught a SIG$sig--shutting downn";
close(LOG);
exit(0);
}
?
? ? ? ? $SIG{'INT'} ?= &;handler;
$SIG{'QUIT'} = &;handler;
?
? ? ? ? ? ? ? ? ...
$SIG{'INT'} ?= 'DEFAULT'; ? # 恢复默认行为
$SIG{'QUIT'} = 'IGNORE'; ? ?# 忽略 SIGQUIT
? ? 设置为 'IGNORE' 值通常具有忽略该信号的效果,除了 "CHLD"信号以外。用 %SIG散列表也可以设置特定的内部拦截点。在即将打印一条警告信息时,由$SIG{__WARN__}、指定的例程会被调用。警告信息作为第一个参数被传递给该例程。__WARN、拦截点的存在会消除通常 要打印到 STDERR、上的警告。你可以利用这一点将警告保存到变量里,或者像这样将警告转、 变为致命错误:
local $SIG{__WARN__} = sub { die $_[0] };
eval $proggie;
eval当抛出一个致命异常时,由 $SIG{__DIE__}指定的例程会被调用。当__DIE__拦截例程返回后,异常处理会像拦截点不存在一样继续进行。除非拦截例、程 本身通过 "goto"、循环退出或 die() 的方式结束。"__DIE__"、处理器在调用过程中被显式关闭,因此你可以在 "__DIE__"、处理器中继续 die。"__WARN__" 也具有类似行为。
? ? ?(18).错误指示器$@ $! $^E $?分别对应Perl解释器,C库,操作系统和外部程序检测到得错误。为了展示这些变量之间的区别,请考虑以下这个使用了单引号引起字符串的 Perl表达式:?
eval q{
? ? ? ? open my $pipe,"/cdrom/install |" or die $!;
? ? ? ? my @res = <$pipe>;
close $pipe or die "bad pipe: $?,$!";
};
当这条语句执行之后,4 个变量都有可能被设置。在需要 "eval" 的字符串没有通过编译(若 "open" 或 "close"导入的原型错误则可能发生)或者 Perl 代码在执行过程中 die() 掉,则 $@变量会被设置。这些情况下 $@ 的值是编译错误信息或 "die" 的参数(其中会内插 $! 和 $?)。(另见 Fatal。)
上面的 eval() 表达式执行后,open()、"<PIPE>" 和 "close" 被翻译成对 C运行库的调用,继而进入操作系统内核。若其中某个调用失败,则 $! 会设置为C 库的 "errno" 值。在少数操作系统下,$^E 可能含有更详细的错误指示,例如“CDROM仓门没有关闭”。不支持扩展错误 信息的系统只是将 $^E 设置为和 $!一样的值。
最后,$? 在外部程序 /cdrom/install 失败时设置为非 0 值。高 8位反映出该程序遇到的特定错误 条件(程序的 exit() 值),低 8位反映失败方式,例如信号致死或核心转储,细节参见 wait(2)。对比仅在检测到错误条件时才设置的 $! 和 $^E,变量 $? 在每个 "wait" 或管道"close" 时都会 设置并冲掉旧值。这一行为更接近 $@,后者在每次 eval()后总是在失败时设置并在成功时清除。
?
3. Perl中Use和require的区别
区别一:跟require不同的是,use只能用于模块的包含,也就是.pm文件。比如:
use ?MyDirectory::MyModule;
实际上,编译器将从@INC指定的目录下去寻找MyModule.pm模块。如果模块名称中包含::双冒号,该双冒号将作为路径分隔符,相当于Unix下的/。编译器将从@INC指定的每个目录下的MyDirectory子目录去寻找MyModule模块
区别二:两个都是包含,但是包含的条件是不一样的。require包含是发生在程序运行期,而use包含是发生在编译期。学过C/C++的人比较容易理解。下面的例子是错误的:
use Config;
if( $Config{'osname'} eq "MSWin32" )?
{?
use Win32Module;?
}?
else
{?
use UnixModule;?
}
正 因为use是发生在编译期,代码没有执行,所以$Config变量的值是无法判断的。在内部,use其实调用了require和import静态函数。 import()函数告诉包哪些特征将要被导入当前包中,这意味着用之前不必验证函数或者变量是否合法。而require是不会调用import()的。
?
?
?
参考/转载:
Perl by example. Third edition
[精华] 【Perl 文档中文化计划】Perl 特殊变量翻译完成http://www.chinaunix.net/jh/25/769567.html
在Perl中Require 和 use 的区别 http://blog.csdn.net/EagleYIN417/archive/2009/04/07/4053613.aspx

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读