標籤:code 技術 部分 shu method 就是 des string sub
目前還沒介紹Perl的物件導向,所以這節內容除了幾個注意點,沒什麼可講的。
以前經常使用大寫字母的控制代碼方式(即所謂的裸字檔案控制代碼,bareword filehandle),現在可以考慮轉向使用變數檔案控制代碼的形式,因為只有使用變數控制代碼的方式,才能建立檔案控制代碼引用。
open DATA,">>","/tmp/a.log" or die "can't open file: $!";open my $data_fh ,">>","/tmp/a.log" or die "can't open file: $!";open my $fh, '<', 'castaways.log' or die "Could not open castaways.log: $!";
裸字檔案控制代碼和變數檔案控制代碼用法是完全一致的,能用裸字檔案控制代碼的地方都可以替換為變數檔案控制代碼:
while( <DATA> ) { ... }while( <$log_fh> ) { ... }
不管使用裸字還是變數檔案控制代碼的方式,在退出檔案控制代碼所在範圍的時候,都會自動關閉檔案控制代碼,無需手動close。
只是需要注意的是,使用變數檔案控制代碼的方式,在say/print輸出的時候,指定檔案控制代碼時需要使用大括弧包圍,以免產生歧義:
print {$data_fh} "your output content";
如果想要讓某個函數指定輸出的檔案控制代碼,也簡單,只需將檔案控制代碼作為一個參數即可:
log_message( $log_fh, 'My name is Mr. Ed' );sub log_message { my $fh = shift; print $fh @_, "\n";}
字串控制代碼
除了可以將控制代碼關聯到檔案(open)、管道、通訊端、目錄(opendir),還可以將控制代碼關聯到字串。也就是將一個變數作為檔案控制代碼的關聯對象,從這個變數讀或從這個變數寫。
例如:
open my $string_fh, '>>', \my $string;open my $string_fh, '<', \$multiline_string;
上面第一句聲明了一個詞法變數$string
(初始化為Undef),同時建立了一個檔案控制代碼$string_fh
,這個檔案控制代碼的輸出對象是詞法變數$string
指向的資料對象。第二句則是從字串$multiline_string
中讀取資料。
現在可以向這個檔案控制代碼中輸出一些資料,它們會儲存到$string
中:
#!/usr/bin/perlopen my $string_fh, ">>",\my $string or die "...$!";print {$string_fh} "first line\n";print {$string_fh} "second line";print $string,"\n"; # 輸出兩行:first line和second line
如果想將流向標準輸出STDOUT預設裝置(終端螢幕)的內容改輸出到字串中,需要小心一些,因為STDOUT畢竟是標準輸出,程式的很多部分可能都需要使用它。所以,盡量在一小片範圍內修改標準輸出的目標。例如,使用大括弧包圍,並將STDOUT進行local化(裸字檔案控制代碼只能用local修飾):
print "1. This goes to the real standard output\n";my $string;{ local *STDOUT; open STDOUT, '>', \ $string; print "2. This goes to the string\n"; $some_obj?>noisy_method(); # this STDOUT goes to $string too}print "3. This goes to the real standard output\n";
檔案控制代碼容器
說法有點高大上,其實就是將檔案控制代碼儲存到資料結構中(例如hash、數組),做一個裝檔案控制代碼的容器。
例如,有一個檔案a.txt,內容如下。現在想將每一行第二列、第三列儲存到以第一列命名的變數中。
malongshuai big 1250malongshuai small 910gaoxiaofang big 1250gaoxiaofang small 450tuner middle 1218wugui middle 199
如下:
use v5.10; # for statewhile( <> ) { state $fhs; # 定義一個hash引用變數 my( $source, $destination, $bytes ) = split; unless( $fhs?>{$source} ) { # 當hash鍵(第一列)不存在時,建立字串控制代碼 open my $fh, '>>', $source or die '...'; $fhs?>{$source} = $fh; } say { $fhs?>{$source} } "$destination $bytes";}
Perl檔案控制代碼引用