## 利用?`open`?和?`<>`?操作符更易讀取文件
使用 Perl 打開并讀取文件很簡單。下面的示例代碼演示如何打開文件, 一行一行地讀取,檢查匹配正則表達式的文本,以及輸出匹配的行。
~~~
open( my $fh, '<', $filename ) or die "Can't open $filename: $!";
while ( my $line = <$fh> ) {
if ( $line =~ /wanted text/ ) {
print $line;
}
}
close $fh;
~~~
總是檢查?`open`?的返回碼是否為真。如果為假,其結果在?`$!`?中。
## 利用?`chomp`?移除結尾的換行符
從文件讀取行時會包含結尾的換行符。假如你有一個文本文件,其第一行是:
~~~
Aaron
~~~
`Aaron`?實際上是 6 個字符`Aaron\n`。此代碼將失敗:
~~~
my $line = <$fh>;
if ( $line eq 'Aaron' ) {
# won't reach here, because it's really "Aaron\n";
}
~~~
要移除?`\n`?及結尾的其他任意空白,調用?`chomp`。
~~~
my $line = <$fh>;
chomp $line;
~~~
現在?`$line`?為 5 個字符長。
## 利用?`$/`?更改行分隔符
可以更改輸入記錄分隔符?`$/`,其默認設置為?`\n`。
設置?`$/`?一次讀取一段。設置?`$/`?為?`undef`?將一次讀取整個文件。 參閱?[perlvar](http://perldoc.perl.org/perlvar.html)?了解細節。
## 一次讀取整個文件
你將注意到新手在讀取文件時會使用下述兩種方法之一:
~~~
open (FILE,$filename) || die "Cannot open '$filename': $!";
undef $/;
my $file_as_string = <FILE>;
~~~
或:
~~~
open (FILE,$filename) || die "Cannot open '$filename': $!";
my $file_as_string = join '', <FILE>;
~~~
選擇兩種中的前者。第二種讀取所有行到數組,然后組合成一個大字符串。 第一種僅讀取到字符串,不會間接創建行列表。
然而最佳的方式是像這樣:
~~~
my $file_as_string = do {
open( my $fh, $filename ) or die "Can't open $filename: $!";
local $/ = undef;
<$fh>;
};
~~~
`do`?塊返回塊中最后求解的值。此方法將?`$/`?設置為局部作用域,所以 超出塊范圍會設置為默認值。如果沒有局部化?`$/`,那么它將保留設置的 值,其他代碼段可能并不期望它被設置為?`undef`。
下面是另一種方法:
~~~
use File::Slurp qw( read_file );
my $file_as_string = read_file( $filename );
~~~
_File::Slurp_?是一次性讀取和寫入的有用模塊,它將在背后做魔術般的快速 處理。
## 利用?`glob()`?獲取文件列表
使用標準的 Shell 展開模式來獲取文件列表。
~~~
my @files = glob( "*" );
~~~
將它們傳遞給?`grep`?來做快速過濾。例如,要獲取文件而非目錄:
~~~
my @files = grep { -f } glob( "*" );
~~~
## 使用?`unlink`?移除文件
Perl 內置函數?`delete`?用來刪除哈希的元素,而非文件系統中的文件。
~~~
my %stats;
$stats{filename} = 'foo.txt';
unlink $stats{filename}; # RIGHT: Removes "foo.txt" from the filesystem
delete $stats{filename}; # WRONG: Removes the "filename" element from %stats
~~~
術語?`unlink`?來自于 Unix 從目錄節點移除文件鏈接的想法。
## 在 Windows 下使用 Unix 風格的目錄
即使 Unix 使用?`/usr/local/bin`,而 Windows 使用?`C:\foo\bar\bat`?這樣的路徑, 你仍然能夠在文件名中使用斜杠。
~~~
my $filename = 'C:/foo/bar/bat';
open( my $fh, '<', $filename ) or die "Can't open $filename: $!";
~~~
在這種情況下,Perl 在打開文件前魔術化地將?`C:/foo/bar/bat`?更改為`C:\foo\bar\bat`。 這也會防止文件名包含未引起的反斜杠所帶來的問題。
~~~
my $filename = "C:\tmp";
~~~
`$filename`?包含 5 個字符:C、:、tab 字符、m、及 p。實際上,它應該寫成:
~~~
my $filename = 'C:\tmp';
my $filename = "C:\\tmp";
~~~
或者你讓 Perl 來照料它:
~~~
my $filename = 'C:/tmp';
~~~