标准输入输出
STDIN可以用于接收键盘输入或是文件输入。在标量上下文中执行该操作时,会返回输入中的下一行。
while <STDIN> { chomp; print "I saw $_"; } foreach <STDIN> { chomp; print; }
看起来上例中的“while”循环和“foreach”的行为完全一样,其实是有些差别的——在while循环里,Per会读取一行输入,把它存入某个变量并且执行循环的主体,接下来它会回去寻找其他输入行;foreach循环中,行输入操作符会在列表上下文中执行(因为foreach需要逐项处理列表内容),因此Perl会将全部内容读入内存,然后才开始执行循环。当需要处理的输入数据长度很大时,比如处理400M大小的Web服务器日志文件,foreach的效率会比while低很多。因此最好的做法是尽量使用while循环,让它每次处理一行。
钻石操作符的输入<>
钻石操作符提供类似 标准Unix工具程序的参数输入方式,例如对于如下Perl程序“my_program”:
while <> { chomp; print; }
如果执行命令“./my_program fred barney betty”,它应该会处理文件fred,接着是barney,最后是betty。(钻石操作符怎么会知道检查命令行参数呢?其实它的参数是来自@ARGV数组)
如果执行命令是没有指定调用参数,程序会从标准输入流采集数据。
当然还有个例外,如果参数中包含连字符“-”,则Perl代码处理到连字符时,会临时改从标准输入读取数据。
Print操作符会读取后续列表中的所有元素,并把每一项一次送到标准输出。
print <>; #相当于Unix下的cat命令 print sort <>; #相当于Unix下的sort命令
如果对print的输出格式不够满意,还可以使用printf来产生格式化过的输出结果。
printf "Hello, %s; your password expires in %d days!\n", $user, $days_to_die;
当然Perl一如既往地提供了更方便的格式"%g" (你可以把"g"当成"General"数字转换)。
一般来说,我们编写printf的格式化字符串时已经确定了替换参数的个数和类型,不过万事没有绝对,下面的例子就是用程序在运行时动态产生格式字符串。
my @items = qw( wilma dino pebbles ); my $format = "The items are: \n" . ("%10s\n" x @items); printf $format, @items;
另外,有个叫Perl Power Tools (PPT)的项目目标就是用perl重写所有经典Unix工具程序,但是在重写shell的时候陷入了难题。PPT项目一度非常有用,因为它使所有便准的工具程序可以运行在非Unix机器上。
Say函数的功能和print的差不多,但在打印每行内容时都会自动加上换行符。所以下面几种写法的输出结果都一样:
use 5.010 print "Hello!\n"; print "Hello!" . "\n"; say "Hello!";
文件句柄
一般使用全大写字母来命名文件句柄,但是有6个个数文件句柄是Perl保留的——STDIN、STDOUT、STDERR、DATA、ARGV以及ARGVOUT。
open CONfig, 'dino'; #打开一个文件 open CONfig, '<dino' #只读方式打开一个文件 open REDROCK, '>fred' #创建一个新的文件,如果已经存在,则清除原有内容并以新内容代替 open LOG, '>>logfile' #追加方式打开一个文件,如果文件不存在,则创建一个新文件
5.6版的Perl里,加入了open的三个参数的写法:
open CONfig, '<', 'dono'; open bedROCK, '>', $file_name; open CONFG, '<:encoding(UTF-8)', $file_name; #使用UTF-8编码打开文件,这种书写方式会确认编码是否正确 open bedROCK, '>:utf8', &logfile_name(); #这种简写的方式不会考虑输入输出的数据是否真的是合法的UTF-8字符串
我们可以通过下面的这条命令打印出说有perl能理解的字符编码清单:
% perl -MEncode -le "print for Encode->encodings(':all')"
除了字符编码之外,数据输入或输出过程中还可以做其他转换操作。比如DOS风格和Unix风格的换行符:
open bedROCK, '>:crlf', $file_name; #按照DOS换行符风格写入文件 open bedROCK, '<:crlf', $file_name; #读取DOS风格的文件
close bedROCK;
出错处理
当Perl遇到致命错误时,你的程序应该立刻中止运行,并发出错误信息告知原因。这样的功能可以用die函数来实现。
if ( ! open LOG, '>>', 'logfile' ) { die "Cannot create logfile: $!"; #die函数会终止程序的运行并打印出错信息 }
"$!"代表可读的系统错误信息。一般来说,当系统拒绝我们的请求时,"$!"会给出一个解释,类似于C语言中调用perror取得的字符串。
如果Perl遇到的错误是非致命的,可以使用warn函数送出警告信息。warn函数的功能就是产生类似于Perl的内置警告信息的信息(比如启用警告信息时,使用某个undef变量却将它当成已有的值来参与计算,就会触发警告信息)。
从Perl 5.10开始,为人称道的autodie编译指令已经成为标准库的一部分。
use autodie;
这条编译指令是靠判别具体操作的类型来工作的。如果Perl内置函数调用了操作系统接口的话,那么中途出现的错误并不是编程人员所能控制的,所以一旦发现系统调用出错,autodie便会自动帮你调用die。
使用文件句柄
以写入或添加方式打开文件后,可以直接使用print或printf将字符串输出到文件中:
print LOG "Captain's log, stardate 3.14159"; printf STDERR "%d percent complete.\n", $done/$total * 100;
如果print/printf的参数列表没有提供文件句柄,则字符串默认被输出到STDOUT。不过可以使用select操作符改变默认的文件句柄,另外还有一个很奇特的变量"$|",当它的值被设为1,就会使当前的默认句柄在每次输出操作后立刻刷新缓冲区。所以,如果要让输出的内容立即显示(比如在读取监视某个耗时程序的实时日志时),应该这么做:
select LOG; # 将默认输出设定为LOG文件句柄 $|= 1; # 不要将LOG的内容保留在缓冲区 select STDOUT; print LOG "This gets written to the LOG at once!\n";
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。