Perl笔记:04、输入与输出

读取标准输入

$line = <STDIN> ; # 读取下一行
chomp ( $line ) ; # 截掉最后的换行符
chomp ( my $line = <STDIN> ) ; # 这一行相当于上面的两行

如果读到文件结尾,“行输入”操作符就会返回undef。这样的设计是为了配合循环使用,可以自然的跳出循环:

while ( defined ( $line = <STDIN> ) ) {
print "I saw $line\n" ;
}

第一行程序代码做了许多事:读取标准输入,将它存入某个变量、检查变量的值是否被定义,以及我们是否该执行while循环的主体(也就是还没有遇到输入的结尾)。因此在循环主体内,我们会在$line变量里看到各行输入的内容。这是很常见的操作,所以perl顺理成章的为它定义了一个简写形式:

while ( ) {
print "I saw $_\n" ;
}

上面的代码和下面的是一样的:

while ( defined ( $_ = ) ) {
print "I saw $_\n" ;
}

钻石操作符输入

还有另外一种读取输入的方法,就是使用钻石操作符 <> 它能让程序在处理调用参数的时候,提供类似于Unix工具程序的功能。

说白了钻石操作符输入和标准的输入唯一区别就是 钻石操作符的来源不是键盘,而是运行命令时给出参数,这个参数一般情况下应该是文件。可以写多个参数。

调用参数

从技术上来说,钻石操作符其实不会去检查调用参数,他的参数其实是来自@ARGV数组。这个数组时由Perl解释 器事先建立的特殊数组,其内容就是由调用参数组成的列表。它和别的数组没有什么不同,只不过在程序开始运 行时,@ARGV里就已经塞满了调用参数。

钻石操作符会查看数组@ARGV以决定改用哪些文件名,如果它找到的是空列表,就会改用标准输入流;否则,就 会使用@ARGV里的文件列表。这表示程序开始运行之后,只要尚未使用钻石操作符,你就可以对@ARGV动手脚。这 样我们可以处理三个特定的文件,不管用户在命令行参数中指定了什么:

@ ARGV = qw # larry moe curly #; 强制让钻石操作符读取这三个文件
while ( <> ) {
chomp ;
print "It was $_ than I saw in some strage-like file!\n" ;
}

输出到标准输出

print操作符的使用前文已经用过多次了

使用printf 格式化输出

my($user,$days_to_die) = ("zyq",28);
printf "Hello,%s;your password expires in $d days!\n",$user,$days_to_die;

printf可用的转换格式很多,要输出恰当的数值形式,可以使用%g,它会按需要自动选择浮点数、整数甚至是指数形式。%d格式代表十进制的整数,它会舍去小数点之后的数字。

在Perl里,printf最常用在字段式的数据输出上,因为大多数的转换格式都可以让你指定宽度。如果数据太长,字段会按需要自动扩展:

printf "m\n",42 # 输出结果为 ----42 (- 代表一个空格)

%s代表字符串格式,所以它的功能其实就是字符串内插,只是它还能设定字段宽度:
printf "s\n","wilma"; # 输出结果为 -----wilma

printf "%-10s\n","wilma"; # 输出结果为 wilma-----

文件句柄

文件句柄是需要进行操作的文件一个标识而已

打开文件句柄

Perl内置了三种文件句柄分别为:STDIN STDOUT STDERR 这三个文件句柄是自动打开的随着程序的终止而自动关闭。

当需要操作其他文件时,我们就需要使用oopen操作符来告诉perl我要打开其它的文件,如下例子:

open CONFIG,"dino"; # 以只读形式打开,此时的CONFIG就像一个指针指向dino文件
open CONFIG,"<fred"; # 同上
open CONFIG,">fred"; # 以复写的形式打开文件
open LOG,">>logfile"; # 以添加的形式打开文件

第一行会打开已经存在的dino文件,文件中的任何内容,都能从文件句柄CONFIG读到我们的程序中来。这和利用shell的重定向(例如<dino这样的写法)将文件内容经STDIN读入程序里的做法相似。实际上第二行正好利用了这样的技巧。它和第一行做所的事实完全相同的。只不过用了小于号来声明“此文件是用来输入的”,而这正是默认的操作。

在相对新的Perl(5.6版以后)中,open另有一种使用三个参数的写法,当然这种写法是规范且一目了然的:
open CONFIG,"<","dino";
open BEDROCK,">",$file_name;
open LOG,">>",&logfile_name();

其优点在于语法上可以很容易的区分模式串(第二个参数)与文件名本身(第三个参数),这种写法在安全方面有些好处。

关闭文件句柄

当不再使用某些文件句柄时要记得使用close操作符来关闭它们,尽管程序结束后会关闭所有的文件句柄,但手工关闭是一个很好的习惯。时刻记得open和close应该是成对出现的

close BEDROCK;

用die处理严重错误

当Perl遇到严重错误时,程序应该终止执行,并用错误信息告知原因。这样的功能用die函数可以实现,它让我们能够自定义“严重错误”信息。

die函数会输出你指定的信息,并且让你的程序立刻终止,并返回不为零的退出码。还有一个很不错的功能,就是可以报告程序出错的行数。

由于有了die命令,那么在上文的打开文件句柄时为了严谨考虑应该判断需要打开的文件是否成功的打开了。如果没有成功打开的话应该报错,如果这个文件很重要的话就必须终止程序的运行。所以上面的例子可以改写成:

if ( ! open LOG , ">>logfile" ) {
die "Cannot create logfile:$!" ;
}

如果open失败,die会终止程序的运行,并且告诉我们无法创建日志文件。后面的$!是可读的系统出错信息。一般情况下,当系统拒绝我们所请求的服务时,$!会给我们一个理由。有可能是权限不够或文件找不到等。

使用文件句柄

当文件句柄与只读的形式打开时,perl可以轻而易举的从中读取数据如下:

if ( ! open PASSWD , "/etc/passwd" ) {
die "How did you get logged in?($!)"
}

while ( <PASSWD> ) {
chomp ;
...
}

正如你所看到的,所谓的“行输入”操作符是由两部分组成的:一对尖括号以及里面用来输入的文件句柄。

以写入或是添加模式打开的文件句柄可以在print或printf函数中使用。使用时,直接将它放在关键字之后、参数列表之前:

print LOG "Captain's log,stardate 3.14159\n"; # 输出到文件句柄LOG
printf STDERR "%d percent complete.\n",$date/$total*100;

注意到文件句柄和好输出的内容之间没有逗号了吗?实际上是可以加个括号的,但这个括号可有可无。

改变默认的文件输出句柄

默认情况下如果不为print或printf指定文件句柄的话,他们的输出就会送到STDOUT。不过可以使用select操作符来改变默认的文件句柄。下面的例子中我们会将输出送到BEDROCK这个文件句柄:

iselect BEDROCK;
print "I hope Mr.Slate doesn't find out about this.\n";
print "Wilma!";

一旦用select操作符切换了默认输出的文件句柄。程序就会一直往那里输出。因此在输出完毕后应该立刻将默认输出切换回来。将文件输出到文件句柄的话默认都会先送到缓冲区内,如果想立刻刷新缓冲区可以将$|变量置为1即将如下代码:

select LOG;
$| = 1 ; # 不要将LOG的内容保留到缓冲区
select STDOUT ;
print LOG "this gets written to the LOG an once!\n" ;

复用标准文件句柄

如果你要复用文件句柄(换句话说,如果已经打开了某个名为FRED的文件句柄,而现在又要打开同样名为FRED的文件句柄),Perl会自动帮你关闭原有的文件句柄。不过要注意,不要复用Perl内置的6个标准文件句柄,除非你想使用该文件句柄实现特殊的功能。前文说过,来自die,warn的信息以及Perl内部的错误信息会送到STDERR。如果以上三个知识能融会贯通,你就会意识到,错误信息不一定送到程序的标准错误输出流,也可以送到文件里,如下:

if ( ! open STDERR , ">>/home/barney/.error_log" ) {
die "Can't open error log for append:$!" ;
}

注意:在成功的打开.error_log文件后STDERR文件句柄才能算是真正意义上的复用了,Perl才会变比默认的系统文件句柄,如果打开文件失败,则不会复用STDERR句柄,Perl会自动返回内置的文件句柄。

使用say来输出

say 函数和print函数类似,都是输出一行信息,但say会自动在末尾加上换行符。其他的使用方法和print一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值