2011-01-19 76 views
1

在Perl中,我試圖逐行讀取文件並處理每一行,並根據需要對其進行修改。 到目前爲止,我正在閱讀的唯一方法就是將文件讀入數組,根據需要修改數組中的每個元素,然後在完成時將其輸出迴文件。如何根據需要修改行來逐行讀取文件?

有沒有更好的方法來做到這一點,也許某種方式,我可以取代單行,因爲我走?

現在,我的處理代碼如下所示:

while (my $line = <FILE>) 
{ 
    # process line here 
    # ........... 

    print FILE $line; 
} 

我的代碼看起來非常接近,但它目前在我行後更換一條線,如此看來,如果我可以將文件指針向上一行,它會寫入文件中的正確位置。

我在正確的軌道上嗎?我需要從這裏做什麼來備份文件指針,以便寫入我正在閱讀的同一行?


編輯:

出我收到的答案,使用local $^ITie::File都很好地工作。 我最終與Tie::File一起去,所以我不必打印出文件的每一行。這樣,如果腳本中途發生某些事情,我的文件不會混亂。

我的新代碼如下所示:

use Tie::File; 

chomp(my $filename = $ARGV[0]); 
tie my @array, 'Tie::File', $filename or die $!; 

foreach my $line(@array) 
{ 
    # ...... line processing happens here ....... 
    # ...... $line is automatically written to file if $line is changed ....... 
} 

回答

5

我不認爲這是一個好主意,從文件中讀取和像你一樣在同一時間寫入。您可以使用Tie::File。它將文件的行與數組綁定在一起。您可以根據需要修改陣列,然後在後臺透明地修改文件。

+0

這正是我在找什麼。謝謝! – 2011-01-19 15:42:14

6

我需要從這裏做什麼來備份文件指針,以便它寫入我正在閱讀的同一行?

這並沒有幫助,除非你每次打算寫行是相同的長度,您要更換線路(在這種情況下,你要尋找的工具seektell)。對於普通的編輯,標準的文件模型並沒有削減它的位置。

幸運的是,Perl附帶了一個功能,可以讓您輕鬆進行所謂的「就地編輯模式」,其中源文件被重命名或取消鏈接,輸出指向同名的新文件。通常通過啓用-icommand-line switch以及-p-n開關進行行式編輯來使用它,但您也可以在使用$^Ispecial variable的程序中啓用它。

示例代碼:

{ # Create a scope to localize variables in. 
    # If you want to back up the originals, set $^I to ".bak" instead. 
    local $^I = ""; 
    # Set @ARGV to the file you want to process, or a list of files. 
    local @ARGV = ("file.txt"); 

    while (my $line = <>) { 
     # Process $line here. 
     print $line; 
    } 
} 
+0

只是給了這個嘗試,它工作得很漂亮!謝謝! – 2011-01-19 15:55:26

0

我傾向於做得一樣在this answer假定(參見sub precommit_hook):

首先,讀入整個文件到一個數組:

open my $handle,'<:utf8',$name 
    or croak "Error reading file contents of $name\n"; 
my @content = <$handle>; 
close $handle or croak "unable to close"; 

然後,處理陣列的每一行並將其寫出到文件中:

# now, write it, ignoring the comment lines 
open my $handle, '>:utf8', $name 
or croak "Opening $name for writing failed\n"; 
flock $handle, LOCK_EX; 

foreach my $line(@content){ 
    # TODO: modify the line here 
    print {$handle} $line . "\n"; 
} 

close $handle or croak "unable to close"; 

這樣做的缺點是整個文件被重寫,並且如果過早退出(例如,在調試期間),文件被搞亂了。

+1

無論如何,如果你所要做的就是關閉它,你不應該使用`flock $ fh,LOCK_UN`來解鎖文件。 `close`會在文件關閉時解鎖文件,但首先它會清除尚未寫入的數據,防止競爭。 – hobbs 2011-01-19 23:16:42

1

可能與問題無關,但可以在命令行上就地對文件進行快速更改,例如,

# convert MS line endings to UNIX: 
perl -p -i -e 's{\r\n}{\n}' my_file.txt 

該生產線是$ _的代碼(以-e參數)和行被打印出來,所以它的就地版本是這樣的:

perl -e '$line = $_; $line =~ s{\r\n}{\n}; print $line' <windows.txt> unix.txt