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,而用新的日誌文件替換了

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