Learning Perl 第五章 輸入和輸出 讀取標準輸入,使用行操做符<STDIN>: $line = <STDIN>; chomp($line); 若是讀到文件結尾,行輸入符就會返回undef. while (defined($line=<STDIN>)) { print "I have seen $line.\n"; } Perl能夠將上述定義簡寫: while (<STDIN>) { print "I have seen $_.\n"; } 行輸入操做符<STDIN>與默認變量($_)之間沒有關聯,只是這個簡寫裏,輸入的內容剛好存儲在默認變量裏面。 for與while的區別,while循環,Perl會讀取一行,而後在尋找其餘輸入行; for循環會將輸入所有讀起來。 另一種讀取輸入的方法,就是使用鑽石操做符<>,它能讓程序在處理參數時,提供相似Unix工具的功能。 程序調用參數(invocation argument)一般是命令行上跟着程序後面的幾個單詞。 $./my_program.pl cao qing 若是把連字符看成參數,則表示從標準輸入讀取數據。假如調用參數cao-qing。程序會先處理cao,而後處理標準輸入流中提供的數據,最後纔是qing。 能夠在程序運行時指定程序的輸入源。 鑽石操做符是行輸入操做符的特例。他不是從鍵盤取得輸入,而是從用戶指定位置讀取: while (<>) { chomp; print "It was $_ that i saw.\n"; } 加入鑽石操做符沒法打開某個文件讀取其中內容時,會出現診斷錯誤。 鑽石操做符不會去檢查命令行參數,它的參數來自於@ARGV數組。該數組就是命令行參數列表。 @ARGV列表與其餘數組相似,進行一樣操做。若是爲空列表,則改用標準輸入流。 @ARGV = qw (cao qing wang huan); while (<>) { chomp; print "I have seen $_.\n"; } 強制讓鑽石操做符讀取上述四個文件。 輸出到標準輸出 print操做符會讀取後續列表中的全部元素。 直接使用數組和使用數組內插是不一樣的: print @array; print "@array"; 第一個會一個接一個的打印全部元素;第二個是打印一個字符串。 @array = qw \ cao qing wang huan\; print @array; print "\n"; print "@array"; caoqingwanghuan cao qing wang huan print處理的是帶打印的字符串列表,因此他的參數在列表上下文執行。而鑽石操做符在列表上下文中返回許多輸入組成的列表,因此他們之間能夠配合工做。 print <>; #Unix cat print sort <>; #Unix sort print後面的括號無關緊要,除非會改變表達式的意義,不然Perl裏的括號能夠省略。 Perl能夠省略括號,可是不要忘記括號的歸屬, printf格式化輸出 printf須要的參數包括格式化字符串和要輸出的數據列表。 元素個數應該和轉換的數目同樣多,不然沒法正常運行。 要輸出恰當的數組形式,可使用%g,它會自動選擇浮點數,整數甚至是指數形式。 print "%g %g %g\n", 5/2, 4, 2 ** 10; %d表示十進制整數,它會無條件階段,而非四捨五入。 %s表明字符串,他的功能就是字符串內插。 若是寬帶字段爲負數,則會左對齊。 數組和printf。通常不會把數組看成printf參數。這是由於數組會包含任意數目的元素,而格式化字符串只會用到固定數目的元素。 能夠在程序中動態的產生格式字符串: my @items = qw (cao qing wang huan); my $format = "The items are: \n" . ("%10s\n" x @items); print "The format is >>$format<<\n"; printf $format, @items; The format is >>The items are: %10s %10s %10s %10s << The items are: cao qing wang huan 注意上下文的重要性。 文件句柄 文件句柄(filehandle)就是程序裏表明Perl進程與外界之間的I/O聯繫的名稱。 能夠把文件句柄的引用放在常規的標量變量裏,不過喜歡使用裸字(bareword)。 建議使用全大寫字母來命名文件句柄。 Perl保留6個特殊文件句柄名:STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT。 打開文件句柄 open CONF, 'dino'; open CONF, '< dino'; open CONF, '> fred'; open CONF, '>> logile'; 第一行和第二行徹底相同,第三行爲打開一個文件句柄並輸出到新文件fred,第四行已追加的方式打開文件句柄。 可使用任意的一個標量表達式來代替文件名說明符。 注意大於號後面的空格。 新版的還能夠接受三個參數,open CONF, '<', 'dino'; 能夠更容易區分模式和文件名自己。還有一個好處就是指定編碼值。 指定讀取的文件爲UTF-8編碼的: open CONF, '<:encoding(utf-8)', 'dino'; 除了編碼以外,數據輸入和輸出還有其餘層能夠控制數據轉換。 解決回車換行能夠藉助:crlf層 open BEDROCK, '>:crlf', $filename; 讀取DOS風格的文件時,能夠:open BEDROCK, "<:crlf", $filename 會自動轉換爲Unix風格的換行符。 以二進制方式讀取文件句柄 Perl5.6之後能夠在binmode的第二個參數位置指定層。若是但願輸出Unicode到STDOUT,就要確保STDOUT知道如何處理拿到的數據: binmode STDOUT, ':encoding(UTF-8)'; 若是知道傳入的是UTF-8編碼的字符: binmode STDIN, ':encoding(UTF-8)'; 有問題的文件句柄,可使用-w和warnings編譯指令來啓用警告功能。 關閉文件句柄 close BEDROCK; die處理致命錯誤,能夠可以本身觸發致命錯誤並給出錯誤信息。 die函數會輸出指定信息到標準錯誤流,並終止程序,返回不爲0的狀態碼。 if (! open LOG, '>>', 'logfile') { die "cannot create logfile: $!"; } open失敗,die會終止程序運行。$!就是可讀的系統錯誤信息。 能夠用warn發出警告信息,可是不會終止程序運行。 autodie編譯指令能夠自動檢測致命錯誤。 use autodie; 使用文件句柄 一旦文件句柄以讀取模式打開,即可以從他讀取一行行數據。 if (! open PASSWD, '<', '/etc/passwd') { die "How did you get logged in?($!)"; } while (<PASSWD>) { chomp; ... } 已寫入或者添加模式打開的文件句柄能夠在print或printf函數中使用。使用時,直接放在函數名以後,參數列表以前。 print LOG "I love you.\n"; print STDERR "I miss you.\n"; 改變默認的文件句柄 select BEDROCK; print "I hope you can love me.\n"; 一旦選擇用了默認文件句柄,文件會一直往哪裏輸出。 select LOG; $| = 1; select STDOUT; print LOG "i love you./n"; 將數據輸出到文件句柄時,默認都會通過緩衝處理,可是隻要將默認變量$|設定爲1,就會是當前的默認文件句柄在每次輸出後馬上刷新緩衝區。 從新打開文件句柄。Perl從新打開文件句柄時,會默認關閉原來那個。