输入与输出

1、读取标准输入

读取标准输入:

chomp($lines = <STDIN>);

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

while(defined($lene = <STDIN>)){

    print"Isaw $line";}

第一行程序代码做了许多事:读取标准输入,将它存入某个变量,检查变量的值是否被定义,以及我们是否该执行while循环的主体,也就是还没遇到输入的结尾。这是十分常见的内容,所以可以简写为:

while(<STDIN>){

    print "I saw $_";}

这里面的尖括号的意思是:读取一行标准输入,看它是不是为真,若是真,就进入while循环,并在下次循环是忘记刚刚读入的那一行,进入下一行。这种简写只在这里有效。

如果在列表上下文中调用“行输入”操作符,它会返回一个列表,其中包含所有的输入内容,每个列表的元素代表一行输入内容:

foreach(<STDIN>){

    print"I saw $_";}

这个程序与while循环的不同,在while循环里,Perl会读取一行输入,把它存入某个变量并且执行循环的主题,接下来,它会回头去寻找其它的输入行。但是在foreach循环里,行输入操作符会在列表上下文中执行,,因为foreach需要逐项处理类表的内容。为此,在循环能够开始执行之前,它必须先将输入全部读进来。

因此,尽量使用while循环的简写,让它每次处理一行。

2、钻石操作符

它能让程序在处理调用参数的时候,提供类似于标准Unix的功能。

程序的调用参数通常是命令行上跟在程序后面的几个单词。

$ ./my_program fred barney betty;

这行命令的意思是:执行my_program命令(它可以在当前的目录中找到),然后它应该处理文件fred,接着是文件barney,最后是文件betty.

若不提供任何调用参数,程序会处理标准输入流,如果把-当作参数,它也代表标准输入。

如果调用的参数是fred - betty,那么程序应该处理文件fred,接着是标准输入流,最后才是文件betty

让程序以这种方式运行的好处,就是逆可以在运行时制定程序的输入源。举例来说,逆不需要重写程序,就可以在管道里使用它,Perl的这个功能,是想帮逆轻松写出类似标准Unix工具的程序,甚至在非Unix的系统也能运行。

钻石操作符是行输入操作符的特例。

while(<>){ chomp; print "It was $_ that I saw!\n";}
这和前面的循环效果相同,但是可以少打些字,这里 chomp的默认用法:不加参数时,chomp 会直接作用在$_上。

调用参数:钻石操作符的调用参数来自@ARGV数组,这个是Perl事先就建立的数组,其内容就是由调用参赛组成的列表。钻石操作符操作的文件名都存储在这个数组里面,我们可以直接操作这个数组。

@AGRV = qw/hello.pl/; while(<>){ chomp; print"It was $_ that I saw stooge-like file!\n";}
这个钻石操作符在指定文件的话会读文件,也可以通过输入-来指定用户的键盘输入,如果没有指定任何的参数,则等待用户的输入。

3print输出到标准输出

输出到标准输出:print操作符会读取一个列表里的所有值,并把每一项,当然是一个字符串,依次送到标准输出。它在每一项之前、之后与之间都不会再加上额外的字符。要是想在每个元素之间加上空白,并在结尾就加上换行符,你得这么做:

$name = "Larry wall"; print "Hello there, $name, did you know that 3+4 is ",3+4, "?\n";
直接使用数组和使用数组内插,在打印效果上是不同的:

print @array; #把数组的元素打印出来fredbarneybetty print "@array"; #打印出一个字符串fred barney betty
第一个 print表达式会一个接着一个打印出数组中所有的元素,元素之间不会有空格。而第二个则不同,它只打印一个字符串,也就是@array 在双引号中内插形成的字符串,也就是数组所有元素的(空格分隔)字符串。

不过第二种也不是没有问题,当@array中的元素后面都含有一个换行符的话,应该使用第一种,会分三行输出其中的元素。但如果使用第二种写法,就会在第二行以后的每个元素前多出一个空格。

一般,如果数组中的字符串包含换行符,那么只要直接将它们输出来就好了:

print @array;

要使它们不包含换行符号,你通常需要在结尾补上一个\n

print "@array\n";

通常在使用引号的场合,字符串后面最好都加上\n

由于Print处理的事待打印的字符串列表,因此它的参数会在列表上下文中执行。而钻石操作符在类表上下文中会返回由许多输入行组策划那个的列表,所以它们彼此可以配合工作。

print <>; #和Unix下的‘cat’命令功能差不多 print sort <>; #和Unix下的‘sort’命令功能差不多
虽然它们不能实现全部功能,但绝对是物超所值。

print后面加括号的问题,一般不加,但加入print的调用看起来像函数调用,它就是一个函数调用。在函数调用里,函数名后面必须紧接着一对括号,里面包含了函数的参数,如下所示:

print (2+3); #它会输出5, print的返回值不是真就是假,代表print是否成功执行。 $result = print("hello world!\n"); #结果一般为1 print (2+3)*4; #以为会输出20,但会输出4,因为print (2+3)的返回值是1。
问题在于 Perl可以省略括号,而大多数人又容易忘记括号的归属。没有括号的时候,print是列表操作符,会把气候列表里的所有东西全都搬出来。一般来说,这就是我们想要的。但是加入print 后面紧跟着左括号,他就是一个函数调用,只会将括号内的东西搬出来。因为该行程序代码有括号,所以上面的程序等同于下面:

(print(2+3) * 4);

4、使用printf格式化输出

%g要输出恰当的数值形式,可以使用,它会按照需要自动选择浮点数,整数甚至是指数形式;

%d代表十进制的整数,它会社区小数点之后的数字,它会无条件舍去,而非四舍五入。可以指定输出数据的宽度,%6d

%s代表字符串格式,所以它的功能其实就是字符串内插,只是它还能设定字段宽度:

printf "%10s\n","wilma"   #看起来像_____wilma

如果宽度是负值,则会向左对齐。

printf "%15s\n","flintstone";   #看起来像flintstone____

%f转换格式(浮点数)会按照需要四舍五入,还可以制定小数点之后的输出位数。

printf "%12f\n",6*7+2/3; #看起来像___42.666667 printf "%12.3f\n",6*7+2/3; #看起来像______42.667 printf "%12.0f\n",6*7+2/3; #看起来像__________43
要输出真正的%,请使用%%

一般来说,你不会将数组当成printf的参数,这是因为数组可以包含任意数目的元素,而格式字符串却只会用到固定数目的元素:加入格式字符串里有三个转换格式,那就必须刚好有三个元素可供使用。但可以这样使用:

my @items = qu(wilma dino pibbles); my $format = "The items are:\n" . ("%10s\n" x @items); print $format,@items;
这段程序使用了 x操作符来复制你所制定的字符串,赋值的辞去与@items的个数相同。在上例中,因为列表有三个元素,所以赋值次数是3。这样一来,产生的格式字符串就和直接写“The items are: \n%10s\n%10s\n%10s\n”一样。程序会先输出标题,接着将每个元素显示成独立的一行,每行都靠右对齐,字段一律10 个字符宽。我们可以把它们全都组合在一起:

printf "The items are: \n".("%10s\n" x @items),@items;

5、文件句柄

文件句柄就是程序里代表Perl进程与外界之间的I/O联系的名字。也就是说,它是“这种联系”的名称,不一定是文件名。

建议使用全大写字母来命名文件句柄。

6个特殊的文件句柄是Perl保留的,它们的名字是

STDIN:标准输入流,它通常是用户的键盘输入,除非用户要求别的输入来源,像从文件读取输入或是经由管道读取另一个程序的输出。

STDOUT:标准输出流,默认情况下它会输出到用户的屏幕,但用户也可以把它送到文件或是另一个程序。

STDERR:即使输出会被重定向到下一个程序或文件,错误信息仍能刘翔用户需要之处。错误信息在默认情况下通常是输出到用户的屏幕,但用户还是可以用如下的shell命令将错误信息转向某个文件:

$ netstat | ./your_program 2>tmp/my_errors

还有DATAARGVARGVOUT

可以在shell中运行一下命令:

$ ./your_program <dino >wilma

这条命令告诉shell程序的输入应该来自文件dino,输出应该送到文件wilma。这个程序只要盲目地从STDIN读进它的输入、按照我们的意思处理这些输入数据,之后再盲目的把输出送到STDOUT,那么这一切就OK了。

也可以使用管道中运行。

$ cat fred barney |sort|./your_program|grep something|lpr

6、打开文件句柄

STDINSTDOUTSTDERR都是由产生Perl进程的父进程自动打开的文件或设备。当需要其他的文件句柄时,使用open操作符告诉Perl,要求操作系统为你的程序和外界架起一道桥梁。

open CONFIG,"dino"; 

打开文件dino,文件中的任何内容,都能从文件句柄CONFIG读到我们的策划那个序中来。

open CONFIG,"<dino";   

功能同上,使用<声明该文件是用来输入的

open BEDROCK,">fred"; 

用来创建一个新的文件:它会打开文件句柄BEDROCK并输出到新文件fred中。如果已经存在一个名为fred的文件,那么就清除原有的内容并且以新内容取代之。

open LOG,">>logfile"; 

使用两个大于号指明以追加的方式来打开文件。即文件原本就存在,那么新的数据将会添加在原有文件内容的后面;如果它不存在,就会创建一个新文件,和只有一个大于符号的情况类似。此特性对于日志文件来说非常方便,逆的程序可以在每次运行时只加几行数据到日志文件里。

可以使用任何的标量表达式来代替文件名说明符,不过一般要明确指定输入或输出的方向:

my $selected_output = "my_output"; open LOG,">$selected_output";
不正确的文件句柄: open 的返回值会告诉我们文件句柄的执行是否成功。返回真表示成功,返回假表示失败。

关闭文件句柄:如果打开一个文件句柄,使用完成后,要关闭文件句柄。使用close来关闭。请为一个open搭配一个close

7、用die处理严重错误

Perl遇到严重错误时(如除以0、使用不合法的正则表达式或调用未定以的子程序),你的程序应该终止运行,并用错误信息告知原因。这样的功能可以用die函数来实现。错误信息保存在Perl的特殊变量$!中。

if(!open LOG,">>logfile"){

    die "cannot create logfile:$!";}

8、使用warn输出警告信息

die可以用来输出Perl的内置错误(比如除以0)。相似的,warn函数的功能就是模拟Perl的内置警告(比如启用警告信息时,使用某个undef变量,却把它当成定义值来用,就会导致内置警告)。

warn函数的功能die函数的差不多,不同之处在于,它不会终止程序的运行。

9、使用文件句柄

当文件句柄以读模式打开后,你可以轻易地从它读取一行数据,就像STDIN读取标准输入流一样。

if(!open PASSWD, "/etc/passwd"){ die "How did you get logged in?($!)";} while(<PASSWD>){ chomp; ...}
这里行输入操作符是由两部分组成:一堆尖括号(真正的行输入操作符)以及以及里面用来输入的文件句柄。

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

print LOG "Captain's log, stardate 3.141596\n"; #输出到文件句柄LOG printf STDERR "%d percent complete.\n",$done/$tontal*100;
注意文件句柄和要输出的内容之间没有逗号。也可以像下面写:

printf (STDERR "%d percent complete.\n", $done/$total*100);

printf STDERR ("%d percent complete.\n", $done/$total*100);

10、改变默认的文件输出句柄

默认情况下,假如部位printprintf指定文件句柄,输出会默认送到STDOUT。但可以使用select操作符来改变默认的文件句柄。

elect BEDROCK; print "I hope Mr. Slate doesn't find out about this.\n"; print "Wilma!\n";
一旦切换了默认暑促的文件句柄,程序就会一直往那里输出。这样会对后面的程序有影响。所以指定的文件句柄使用完后,最好把它设回原先的默认值 STDOUT来。设定特殊变量$|1 的话,就会使当前的默认文件句柄在每次进行输出操作后,立刻刷新缓冲区。所以,如果要让输出的内容立即显示,可以这么做:

select LOG;

$| = 1;

select STDOUT;

...

print LOG "This gets written to the Log at once!\n";

11、复用文件句柄

错误信息不一定都要送到程序的标准错误输出流,也可以送到文件。

#将错误信息写到自定的错误日志中

if(!open STDERR,">>/home/barney/.error_log"){ die "Can't open error log for append:$!";
使用了 STDERR之后,任何从Perl 产生的错误信息都会送到新的文件里。

12、使用say来输出

Perl5.10say这个函数。它的功能和print差不多,但是会在每行输出的结尾自动加上换行符,下面的方式输出的结果是一样的:

use 5.010; print "hello!\n"; print "hello!", "\n"; say "hello";
在你想输出某些内容并换行的时候,这个函数非常好用:

use 5.010; my $name = "fred"; print "$name\n"; print $name,"\n"; say $name;
在数组内插的时候,仍然需要将它用引号扩起来,这样它能把数组的元素用空格分开:

use 5.010; my @array = qw(a b c d); say @array #输出"abcd\n" say "@array"; #输出"a b c d\n";
print函数一样,可以为say 指定一个文件句柄:

use 5.010;

say BEDROCK "hello";

你可能感兴趣的:(输出)