?? perl 語言-perl 中文教程(第十一章).htm
字號:
<LI>printf:格式化字符串并輸出到文件 </LI></UL></BLOCKQUOTE>
<P> 這里簡單回顧一下,再講一些前面未提到的函數。<BR><A
name=1.1.1>1)open函數</A><BR> open函數將文件變量與某文件聯系起來,提供訪問文件的接口,例如:open(MYVAR,
"/u/file");
如果文件打開成功,則返回非零值,否則返回零。缺省地,open打開文件用以讀取其內容,若想打開文件以寫入內容,則在文件名前加個大于號:open(MYVAR,
">/u/file"); 向已有的文件末尾添加內容用兩個大于號:open(MYVAR, ">>/u/file");
若想打開文件作為數據導向的命令,則在命令前加上管道符(|):open(MAIL, "|mail dave");<BR><A
name=1.1.2>2)用open重定向輸入</A><BR> 可以把打開的文件句柄用作向程序輸入數據的命令,方法是在命令后加管道符(|),如:<BR> open(CAT,
"cat file*|");<BR> 對open的調用運行命令cat file*
,此命令創建一個臨時文件,這個文件的內容是所有以file打頭的文件的內容連接而成,此文件看作輸入文件,可用文件變量CAT訪問,如:<BR> $input
= <CAT>;<BR> 下面的例子使用命令w的輸出來列出當前登錄的所有用戶名。<BR></P>
<BLOCKQUOTE>
<P>1 : #!/usr/local/bin/perl<BR>2 :<BR>3 : open (WOUT, "w|");<BR>4 :
$time = <WOUT>;<BR>5 : $time =~ s/^ *//;<BR>6 : $time =~ s/
.*//;<BR>7 : <WOUT>; # skip headings line<BR>8 : @users = <WOUT>;<BR>9 :
close (WOUT);<BR>10: foreach $user (@users) {<BR>11: $user =~ s/
.*//;<BR>12: }<BR>13: print ("Current time: $time");<BR>14: print
("Users logged on:\n");<BR>15: $prevuser = "";<BR>16: foreach $user
(sort @users) {<BR>17: if ($user ne $prevuser) {<BR>18:
print ("\t$user");<BR>19: $prevuser = $user;<BR>20:
}<BR>21: } </P></BLOCKQUOTE>
<P> 結果輸出如下:<BR></P>
<BLOCKQUOTE>
<P>Current time: 4:25pm<BR>Users logged on:<BR> dave<BR>
kilroy<BR> root<BR> zarquon </P></BLOCKQUOTE>
<P> w命令列出當前時間、系統負載和登錄的用戶,以及每個用戶的作業時間和當前運行的命令,如:<BR></P>
<BLOCKQUOTE><PRE> 4:25pm up 1 day, 6:37, 6 users, load average: 0.79, 0.36, 0.28
User tty login@ idle JCPU PCPU what
dave ttyp0 2:26pm 27 3 w
kilroy ttyp1 9:01am 2:27 1:04 11 -csh
kilroy ttyp2 9:02am 43 1:46 27 rn
root ttyp3 4:22pm 2 -csh
zarquon ttyp4 1:26pm 4 43 16 cc myprog.c
kilroy ttyp5 9:03am 2:14 48 /usr/games/hack
</PRE></BLOCKQUOTE>
<P> 上例中從w命令的輸出中取出所需的信息:當前時間和登錄的用戶名。第3行運行w命令,此處對open的調用指定w的輸出用作程序的輸入,用文件變量WOUT來訪問該輸入。第4行讀取第一行信息,即:<BR> 4:25pm
up 1 day, 6:37, 6 users, load average: 0.79, 0.36,
0.28<BR> 接下來的兩行從這行中抽取出時間。首先,第5行刪除起始的空格,然后第6行刪去除時間和結尾換行符之間的所有字符,存入變量$time。<BR> 第7行從WOUT讀取第二行,這行中無有用信息,故不作處理。第8行把剩下的行賦給數組@users,然后第9行關閉WOUT,終止運行w命令的進程。<BR> @users中的每個元素都是一行用戶信息,因為本程序只需要每行的第一個單詞,即用戶名,故10~12行去掉除換行符外的其它字符,這一循環結束后,@users中只剩下用戶名的列表。<BR> 第13行輸出存貯在$time中的時間,注意這時print不需要加上換行符,因為$time中有。16~21行對@users中的用戶名排序并輸出。因為同一個用戶可以多次登錄,所以用$preuser存貯輸出的最后一個用戶名,下次輸出數組元素$user時,如果其與$preser相等,則不輸出。<BR><A
name=1.1.3>3)文件重定向</A><BR> 許多UNIX
shell可以把標準輸出文件(STDOUT)和標準錯誤文件(STDERR)都重定向到同一個文件,例如在Bourne
Shell(sh)中,命令<BR> $ foo > file1
2>&1<BR> 運行命令foo并把輸出到標準輸出文件和標準錯誤文件的內容存貯到文件file1中。下面是用Perl實現這一功能的例子:<BR></P>
<BLOCKQUOTE>
<P>1: #!/usr/local/bin/perl<BR>2: <BR>3: open (STDOUT, ">file1") ||
die ("open STDOUT failed");<BR>4: open (STDERR, ">&STDOUT") ||
die ("open STDERR failed");<BR>5: print STDOUT ("line 1\n");<BR>6: print
STDERR ("line 2\n");<BR>7: close (STDOUT);<BR>8: close (STDERR);
</P></BLOCKQUOTE>
<P> 運行后,文件file1中的內容為:<BR>
line 2<BR> line
1<BR> 可以看到,這兩行并未按我們想象的順序存貯,為什么呢?我們來分析一下這段程序。<BR> 第3行重定向標準輸出文件,方法是打開文件file1將它與文件變量STDOUT關聯,這也關閉了標準輸出文件。第4行重定向標準錯誤文件,參數>&STDOUT告訴Perl解釋器使用已打開并與STDOUT關聯的文件,即文件變量STDERR指向與STDOUT相同的文件。第5、6行分別向STDOUT和STDERR寫入數據,因為這兩個文件變量指向同一個文件,故兩行字符串均寫到文件file1中,但順序卻是錯誤的,怎么回事呢?<BR> 問題在于UNIX對輸出的處理上。當使用print(或其它函數)寫入STDOUT等文件時,UNIX操作系統真正所做的是把數據拷貝到一片特殊的內存即緩沖區中,接下來的輸出操作繼續寫入緩沖區直到寫滿,當緩沖區滿了,就把全部數據實際輸出。象這樣先寫入緩沖區再把整個緩沖區的內容輸出比每次都實際輸出所花費的時間要少得多,因為一般來說,I/O比內存操作慢得多。<BR> 程序結束時,任何非空的緩沖區都被輸出,然而,系統為STDOUT和STDERR分別維護一片緩沖區,并且先輸出STDERR的內容,因此存貯在STDERR的緩沖區中的內容line
2出現在存貯在STDOUT的緩沖區中的內容line
1之前。<BR> 為了解決這個問題,可以告訴Perl解釋器不對文件使用緩沖,方法為:<BR>
1、用select函數選擇文件<BR>
2、把值1賦給系統變量$|<BR> 系統變量$|指定文件是否進行緩沖而不管其是否應該使用緩沖。如果$|為非零值則不使用緩沖。$|與系統變量$~和$^協同工作,當未調用select函數時,$|影響當前缺省文件。下例保證了輸出的次序:<BR></P>
<BLOCKQUOTE>
<P>1 : #!/usr/local/bin/perl<BR>2 : <BR>3 : open (STDOUT, ">file1")
|| die ("open STDOUT failed");<BR>4 : open (STDERR, ">&STDOUT")
|| die ("open STDERR failed");<BR>5 : $| = 1;<BR>6 : select
(STDERR);<BR>7 : $| = 1;<BR>8 : print STDOUT ("line 1\n");<BR>9 : print
STDERR ("line 2\n");<BR>10: close (STDOUT);<BR>11: close (STDERR);
</P></BLOCKQUOTE>
<P> 程序運行后,文件file1中內容為:<BR>
line 1<BR> line
2<BR> 第5行將$|賦成1,告訴Perl解釋器當前缺省文件不進行緩沖,因為未調用select,當前的缺省文件為重定向到文件file1的STDOUT。第6行將當前缺省文件設為STDERR,第7行又設置$|為1,關掉了重定向到file1的標準錯誤文件的緩沖。由于STDOUT和STDERR的緩沖均被關掉,向其的輸出立刻被寫到文件中,因此line
1出現在第一行。<BR><A
name=1.1.4>4)指定讀寫權限</A><BR> 打開一個既可讀又可寫的文件方法是在文件名前加上"+>",如下:<BR>
open (READWRITE,
"+>file1");<BR> 此語句打開既可讀又可寫的文件file1,即可以重寫其中的內容。文件讀寫操作最好與庫函數seek和tell一起使用,這樣可以跳到文件任何一點。<BR> 注:也可用前綴"+<"指定可讀寫權限。<BR><A
name=1.1.5>5)close函數</A><BR> 用于關閉打開的文件。當用close關閉管道,即重定向的命令時,程序等待重定向的命令結束,如:<BR>
open (MYPIPE, "cat file*|");<BR> close
(MYPIPE);<BR> 當關閉此文件變量時,程序暫停運行,直到命令cat
file*運行完畢。<BR><A name=1.1.6>6)print,
printf和write函數</A><BR> print是這三個函數中最簡單的,它向指定的文件輸出,如果未指定,則輸出到當前缺省文件中,如:<BR>
print ("Hello, there!\n");<BR> print OUTFILE
("Hello,
there!\n");<BR> 第一句輸出到當前缺省文件中,若未調用select,則為STDOUT。第二句輸出到由文件變量OUTFILE指定的文件中。<BR> printf函數先格式化字符串再輸出到指定文件或當前缺省文件中,如:<BR>
printf OUTFILE (“You owe me %8.2f",
$owing);<BR> 此語句取出變量$owing的值并替換掉串中的%8.2f,%8.2f是域格式的例子,把$owing的值看作浮點數。<BR> write函數使用輸出格式把信息輸出到文件中,如:<BR>
select (OUTFILE);<BR> $~ =
"MYFORMAT";<BR>
write;<BR> 關于printf和write,詳見《第x章 格式化輸出》。<BR><A
name=1.1.7>7)select函數</A><BR> select函數將通過參數傳遞的文件變量指定為新的當前缺省文件,如:<BR>
select
(MYFILE);<BR> 這樣,MYFILE就成了當前缺省文件,當對print、write和printf的調用未指定文件時,就輸出到MYFILE中。<BR><A
name=1.1.8>8)eof函數</A><BR> eof函數查看最后一次讀文件操作是否為文件最后一個記錄,如果是,則返回非零值,如果文件還有內容,返回零。<BR> 一般情況下,對eof的調用不加括號,因為eof和eof()是等效的,但與<>操作符一起使用時,eof和eof()就不同了。現在我們來創建兩個文件,分別叫做file1和file2。file1的內容為:<BR>
This is a line from the first file.<BR> Here is
the last line of the first
file.<BR> file2的內容為:<BR>
This is a line from the second and last file.<BR>
Here is the last line of the last
file.<BR> 下面就來看一下eof和eof()的區別,第一個程序為:<BR></P>
<BLOCKQUOTE>
<P>1: #!/usr/local/bin/perl<BR>2: <BR>3: while ($line = <>)
{<BR>4: print ($line);<BR>5: if (eof) {<BR>6:
print ("-- end of current file --\n");<BR>7: }<BR>8: }
</P></BLOCKQUOTE>
<P> 運行結果如下:<BR></P>
<BLOCKQUOTE>
<P>$ program file1 file2<BR>This is a line from the first file.<BR>Here
is the last line of the first file.<BR>-- end of current file --<BR>This
is a line from the second and last file.<BR>Here is the last line of the
last file.<BR>-- end of current file --<BR>$ </P></BLOCKQUOTE>
<P> 下面把eof改為eof(),第二個程序為:<BR></P>
<BLOCKQUOTE>
<P>1: #!/usr/local/bin/perl<BR>2: <BR>3: while ($line = <>)
{<BR>4: print ($line);<BR>5: if (eof()) {<BR>6:
print ("-- end of output --\n");<BR>7: }<BR>8: }
</P></BLOCKQUOTE>
<P> 運行結果如下:<BR></P>
<BLOCKQUOTE>
<P>$ program file1 file2<BR>This is a line from the first file.<BR>Here
is the last line of the first file.<BR>This is a line from the second
and last file.<BR>Here is the last line of the last file.<BR>-- end of
output --$ </P></BLOCKQUOTE>
<P> 這時,只有所有文件都讀過了,eof()才返回真,如果只是多個文件中前幾個的末尾,返回值為假,因為還有要讀取的輸入。<BR><A
name=1.1.9>9)間接文件變量</A><BR> 對于上述各函數open, close,
print, printf, write,
select和eof,都可以用簡單變量來代替文件變量,這時,簡單變量中所存貯的字符串就被看作文件變量名,下面就是這樣一個例子,此例很簡單,就不解釋了。需要指出的是,函數open,
close, write, select和eof還允許用表達式來替代文件變量,表達式的值必須是字符串,被用作文件變量名。<BR></P>
<BLOCKQUOTE>
<P>1: #!/usr/local/bin/perl<BR>2: <BR>3: &open_file("INFILE", "",
"file1");<BR>4: &open_file("OUTFILE", ">", "file2");<BR>5: while
($line = &read_from_file("INFILE")) {<BR>6:
&print_to_file("OUTFILE", $line);<BR>7: }<BR>8: <BR>9: sub open_file
{<BR>10: local ($filevar, $filemode, $filename) = @_;<BR>11:
<BR>12: open ($filevar, $filemode . $filename) ||<BR>13:
die ("Can't open $filename");<BR>14: }<BR>15: sub read_from_file
{<BR>16: local ($filevar) = @_;<BR>17: <BR>18:
<$filevar>;<BR>19: }<BR>20: sub print_to_file {<BR>21:
local ($filevar, $line) = @_;<BR>22: <BR>23: print $filevar
($line);<BR>24: } </P></BLOCKQUOTE>
<P><A name=1.2></A><FONT color=#003333>2、跳過和重讀數據</FONT> </P>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD width=55>
<DIV align=center><B>函數名</B></DIV></TD>
<TD width=516><B>seek</B></TD></TR>
<TR>
<TD width=55>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD width=516>seek (filevar, distance, relative_to);</TD></TR>
<TR>
<TD width=55>
<DIV align=center><B>解說</B></DIV></TD>
<TD
width=516>在文件中向前/后移動,有三個參數:<BR>1、filevar,文件變量<BR>2、distance,移動的字節數,正數向前移動,負數往回移動<BR>3、reletive_to,值可為0、1或2。為0時,從文件頭開始移動,為1時,相對于當前位置(將要讀的下一行)移動,為2時,相對于文件末尾移動。<BR>運行成功返回真(非零值),失敗則返回零,常與tell函數合用。</TD></TR></TBODY></TABLE><BR>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD>
<DIV align=center><B>函數名</B></DIV></TD>
<TD><B>tell</B></TD></TR>
<TR>
<TD>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD>tell (filevar);</TD></TR>
<TR>
<TD>
<DIV align=center><B>解說</B></DIV></TD>
<TD>返回從文件頭到當前位置的距離。<BR>注意:<BR>1、seek和tell不能用于指向管道的文件變量。<BR>2、seek和tell中文件變量參數可使用表達式。</TD></TR></TBODY></TABLE>
<P><A name=1.3></A><FONT color=#003333>3、系統讀寫函數 </FONT></P>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD width=54>
<DIV align=center><B>函數名</B></DIV></TD>
<TD width=517><B>read</B></TD></TR>
<TR>
<TD width=54>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD width=517>read (filevar, result, length, skipval);</TD></TR>
<TR>
<TD width=54>
<DIV align=center><B>解說</B></DIV></TD>
<TD
width=517>read函數設計得與UNIX的fread函數等效,可以讀取任意長度的字符(字節)存入一個簡單變量。其參數有四個:<BR>1、filevar:文件變量<BR>2、result:存貯結果的簡單變量(或數組元素)<BR>3、length:讀取的字節數<BR>4、skipval:可選項,指定讀文件之前跳過的字節數。<BR>返回值為實際讀取的字節數,如果已到了文件末尾,則返回零,如果出錯,則返回空串。</TD></TR></TBODY></TABLE><BR>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD>
<DIV align=center><B>函數名</B></DIV></TD>
<TD><B>sysread</B></TD></TR>
<TR>
<TD>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD>sysread (filevar, result, length, skipval);</TD></TR>
<TR>
<TD>
<DIV align=center><B>解說</B></DIV></TD>
<TD>更快的讀取數據,與UNIX函數read等效,參數與read相同。</TD></TR></TBODY></TABLE><BR>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD>
<DIV align=center><B>函數名</B></DIV></TD>
<TD><B>syswrite</B></TD></TR>
<TR>
<TD>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD>syswrite (filevar, data, length, skipval);</TD></TR>
<TR>
<TD>
<DIV align=center><B>解說</B></DIV></TD>
<TD>更快的寫入數據,與UNIX函數write等效,參數:<BR>1、filevar:將要寫入的文件<BR>2、data:存貯要寫入數據的變量<BR>3、length:要寫入的字節數<BR>4、skipval寫操作之前跳過的字節數。</TD></TR></TBODY></TABLE>
<P><A name=1.4></A><FONT color=#003333>4、用getc讀取字符 </FONT></P>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD>
<DIV align=center><B>函數名</B></DIV></TD>
<TD><B>getc</B></TD></TR>
<TR>
<TD>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD>$char = getc (infile);</TD></TR>
<TR>
<TD>
<DIV align=center><B>解說</B></DIV></TD>
<TD>從文件中讀取單個字符。</TD></TR></TBODY></TABLE>
<P><A name=1.5></A><FONT color=#003333>5、用binmode讀取二進制文件</FONT> </P>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD width=57>
<DIV align=center><B>函數名</B></DIV></TD>
<TD width=514><B>binmode</B></TD></TR>
<TR>
<TD width=57>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD width=514>binmode (filevar);</TD></TR>
<TR>
<TD width=57>
<DIV align=center><B>解說</B></DIV></TD>
<TD
width=514>當你的系統(如類DOS系統)對文本文件和二進制文件有所區別時使用。必須在打開文件后、讀取文件前使用。</TD></TR></TBODY></TABLE>
<P><A name=2></A><FONT color=#003333>二、目錄處理函數</FONT> </P>
<TABLE class=myFont borderColor=forestgreen cellSpacing=0 cellPadding=2
border=1>
<TBODY>
<TR>
<TD>
<DIV align=center><B>函數名</B></DIV></TD>
<TD><A name=2.1><B>mkdir</B></A></TD></TR>
<TR>
<TD>
<DIV align=center><B>調用語法</B></DIV></TD>
<TD>mkdir (dirname, permissions);</TD></TR>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -