perl学习日记5输入与输出

1.    输入与输出

1.1      从标准输入设备输入

由于,行输入操作在到达文件的结尾时将返回undef,这对于从循环退出时非常方便的:

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

print “I saw $line”;

}

可以这样简写:

while(<STDIN>){

print “I saw $_”;

}

下面这个东西和上面表面上没有区别,实际上它是先得到列表的所有元素再打印的,这样如果是文件很大,就很浪费资源,而上面的就很好,动态利用内存,一个元素一个元素的处理。

foreach(<STDIN>){

print “I saw $_”;

}

1.2      <>输入

$ ./my_program fred barney betty

上述命令的含义是,运行my_program(在当前目录下),它将处理文件fred,再处理文件barney,最后是文件betty

如果没有命令行参数,程序将处理标准输入流(standard input stream)。作为一个特例,如果将连接号(-)作为一个参数,其

含义也是标准输入◆。如果调用参数为fred –betty,其含义是程序将首先处理文件fred,其次是标准输入流,最后是文件betty

while (defined($line = <>)){

chomp($line);

print “It was &line that I saw!/n”;

}

应该想得到,<STDIN>代表标准输入,那么<>就应该代表所有有可能的输入,可以是文件,可以是标准输入。

可以简化的很牛逼:

while(<>){

chomp;

print “It was $_ that I saw!/n”;

}

1.3      调用参数

实际上<>从数组@ARGV 中得到调用参数。这个数组是Perl 中的一个特殊数组,其包含调用参数的列表。那程序名存在哪里了呢?和shell差不多,在$0里面。

@argv = qw# larry mor curly #; #强制使用这三个文件

while(<>){

chomp;

print “It was $_ that I saw in some stooge-like file!/n”;

}

1.4      Print输出到标准输出

print @array; #打印出元素的列表

print “@array”; #打印一个字符串(包含一个内插的数组)

第一个语句打印出所有的元素,一个接着一个,其中没有空格。第二个打印出一个元素,它为@array 的所有元素,其被存在一个字符串中。也就是说,打印出@array 的所有元素,并由空格分开◆。如果@array 包含qw /fred barney betty /◆,则第一个例子输出为:fredbarneybetty,而第二个例子输出为fred barney betty(由空格分开)。

 

例子:

#!/usr/bin/perl

@array = <STDIN>;

print @array;

print "@array";

输出:

legend@ubuntu:~/data/study/perl$ perl 5.4

legend1

legend2

legend3

legend1

legend2

legend3

legend1

 legend2

 legend3

其中前三项是我自己的输入,之后是ctrl+d结束输入。后面六个是程序输出。由于他们是unchomp的,所以每个元素后面都有换行。注意最后两个空格,是数组作为字符串时系统自动添加的。

所以如果,字符串包含换行符,如果想输出它们,通常:

print @array;

如果不包含换行符,通常想加上一个:

print “@array/n”;#注意之前说过的它与print @array.”/n”;的区别

由于print 需要一些输出的字符串列表,则其参数是作为列表context 来求值的。由于<>操作返回的是列表,则它们可很好

的一起工作:

print <>; # ‘cat’的源程序

print sort <>; #‘sort’的源程序

 

print 的括号在不影响语义的情况下是可选的

print (“Hello, world!/n”); #真实语义是将print作为函数调用

pirnt “Hello, world!/n” #真实语义是将print后面的所有东西当作列表打印

所以:print (2+3)*4; #oops!结果是打印了5,丢了运行结果4,因为此时print是系统调用,相当于(print (2+3)) * 4;

1.5      使用printf 格式化输出

printf “Hello, %s; your password expires in %d days!/n”,

$user, $days_to_die;

print “in %d days!/n”,17.85; #in 17 days!

printf “%6f/n”, 42; #输出为○○○○42此处指代空格)

printf “%23/n”,2e3+1.95; #2001

printf “%10s/n”, “wilma”; #输出为:○○○○○wilma

print “%-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

下面一个例子好好理解printfprint的区别

#!/usr/bin/perl

printf "i want to see%%dlegend/n",23; #输出%的正确方法

printf "i want to see/%dlegend/n",23;#别以为和c语言一样,此时应该特别注意

printf "i want to see %d and %s/n",23;#内容不够,则省

printf "i want to see %d and %s/n",23,43,212;#格式符不够则省

结果:

legend@ubuntu:~/data/study/perl$ perl 5.5

i want to see%dlegend

i want to see23legend

i want to see 23 and

i want to see 23 and 43

1.5.1.数组和printf

my @items = qw( wilma dino pebbles );

my $format = “The items are:/n”. (“%10s/n”x @items);

## print“the format is >>$format<</n”; #用于调试

printf $format, @items;

 

printf“The items are:/n”. (“%10s/n”x @items), @items;

1.6      句柄

Perl 自身有六个文件句柄:STDINSTDOUTSTDERRDATAARGVARGVOUT

 

$ ./your_program <dino >Wilma

上述命令告诉shell,从一个名叫dino 读入,将结果输出到叫做wilma 的文件之中。由于程序从STDIN 读入,处理它(按照我们的要求),再输出到STDOUT,上述代码将能很好工作。

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

1.7      文件句柄的打开

open CONFIG, “dino”;

open CONFIG, “<dino”; #和上者一样,因为<是可以缺省的

open BEDROCK, “>fred”;#把文件fred当作标准输出

open LOG,“>>logfile”;#不是新建一个文件或者清空这个文件,而是从后面追加

 

可以在文件名的地方使用任何的标量表达式,虽然通常你可能不想这样做:

my $selected_output = “my_output”;

open LOG,“> $selected_output”    #$selected_output >passwd,则它将

变成追加。

Perl 的新版本中(从Perl5.6 开始),open 支持“参数”类型:

open CONFIG, “<”, “dino”;

open BEDROCK, “>”, $file_name;

open LOG, “>>”, &logfile_name();

这种方法的优点是Perl 不会将模式(第二个参数)和文件的名字(第三个参数)混淆,这能增加安全性

1.7.1.Bad 文件句柄

 

如果从一个bad 文件句柄读入(文件句柄没有恰当的打开),会立刻到达文件结尾(end-of-file)。如果写到一个bad 文件句柄,数据会被悄悄地丢掉。

如何判断文件句柄是否被正确地打开?

-w可以给予警告

也可以用open调用的返回值判断

my $success = open LOG, “>>logifle”; #将返回值保存在$success 

if(!$success){

#打开失败时

...

}

1.7.2.关闭文件句柄

close BEDROCK;

当关闭文件句柄时,Perl 将告诉操作系统已经结束了对此数据流的操作,因此应当将输出的数据写到磁盘中,如果程序重新打开它(也就是说,使用open 重新打开此文件句柄),或者退出程序,Perl 将自动关闭文件句柄。

如果希望程序更加整洁,则每一个open 都应当使用一个close。通常,最好在不使用一个文件句柄时就立刻将它关闭,无论程序是否立即结束

1.8      严重错误和die

 

die 函数将打印出你给它的消息(利用标准错误流),并确保程序退出时为非零(nonzero)的退出状态(exit status

if(!open LOG, “>>logfile”){

die “Cannot create logfile:$!”;

}

如果open 失败,则die 将结束程序,通常,当系统拒绝了我们的请求(如打开文件),$!将告诉你原因(可能是权限不够(permission denied)”或者“(文件不存在)file not found”,针对本例)

 

也可以不用打印系统输出,因为有时根本就没有系统错误输出

if(@ARGV < 2){

die “Not enough arguments/n”;

}

 

1.9      警告信息和warn

warn 函数像die 那样工作,除了最后一步,它不会从程序中退出。

1.10 使用文件句柄

读入:

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”, $done/$total * 100;

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

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

都是正确的

1.10.1.              改变默认的输出句柄

默认情况下,如果不指定文件句柄给print(或者printf,这里的内容对两者均适用),则默认会使用STDOUT。但这个默认属性,可以通过select 操作进行更改。如下:

select BEDROCK;

print “I hope Mr. Slate doesn’t find out about this./n”;

print “Wilma!/n”

以后的print都受影响,因此要及时恢复回去,用select STDOUT;

 

$| = 1; #don’t keep LOG entries sitting in the buffer,设置它为1可以让print语句执行之后立即将文件句柄的内容写入文件

select STDOUT;

#...time passes, babies learn to work, tectonic plates shift, and then … .

print LOG “This gets written to the LOG at once!/n”;

1.11 重新打开文件句柄

if(! Open STDERR, “>>/home/barney/.error_log”){

die “Can’t open error log for append: $!”;

}

因为STDERR默认打开的,所以立即关闭了原有的STDERR,而用新的日志文件替换了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章