2010-02-22 139 views
7

我正在尋找一種方法來讀取輸入文件,並在Perl中只打印選擇行到輸出文件。我要打印到輸出文件的行全部以xxxx.xxxx.xxxx開頭,其中x是字母數字字符(週期是句點,而不是通配符)。線條並不都具有相同的結尾,如果這有所作爲。我正在考慮類似以下內容(據我所知,if聲明的條件完全是缺失的)。如何在Perl中只寫一個文件的某些行?

open(IN, "<$csvfile"); 
my @LINES = <IN>; 
close(IN); 
open(OUT, ">$csvnewfile"); 
print OUT @LINES if ([line starts with xxxx.xxxx.xxxx]); 
close(OUT); 

在此先感謝!

回答

8

這是通過您的線路迴路更好的辦法。它避免了加載你的整個輸入文件到內存中一次:

use strict; 
use warnings; 

open my $fhi, '<', $csvfile or die "Can not open file $csvfile: $!"; 
open my $fho, '>', $csvnewfile or die "Can not open file $csvnewfile: $!"; 
while (<$fhi>) { 
    print $fho $_ if m/^ \w{4} \. \w{4} \. \w{4} /x; 
} 
close $fho; 
close $fhi; 

記住的是,\w字符類還包括下劃線。爲了避免下劃線:

print $fho $_ if m/^ [a-z\d]{4} \. [a-z\d]{4} \. [a-z\d]{4} /xi; 
+2

您可能想要爲該第二個正則表達式添加'/ i'修飾符以及... – 2010-02-22 22:48:56

+1

謝謝!唯一缺少的是在'if'語句中的'$ fho'後面的'$ _'(花了我一段時間才發現,實際上...) – ryantmer 2010-02-22 22:55:19

+1

@ryantmer:是的,我的代碼沒有經過測試。我更新了我的帖子。我懶得創建任何虛假輸入來測試我的代碼,這就是爲什麼提供一個小樣本輸入與您的問題是一個好主意。 – toolic 2010-02-22 23:41:50

1
if ($_ =~ m/^\w{4}\.\w{4}\.\w{4}/i) 

認爲。我的perl有點生疏。

0

如果你不介意把它當作一個命令行1班輪:

perl -ne "print if /^.{4}[.].{4}[.].{4}/" csvfile.csv > csvnewfile.csv 
3

風格提示:

  • 使用詞法文件句柄
  • 檢查open
  • 也是一個好主意,結果檢查手柄上開設了寫字close結果

請參閱下面:

#! /usr/bin/perl 

use warnings; 
use strict; 

die "Usage: $0 old new\n" unless @ARGV == 2; 

my($csvfile,$csvnewfile) = @ARGV; 

open my $in, "<", $csvfile or die "$0: open $csvfile: $!"; 
open my $out, ">", $csvnewfile or die "$0: open $csvnewfile: $!"; 

while (<$in>) { 
    print $out $_ if /^\w{4}\.\w{4}\.\w{4}/; 
} 

close $out or warn "$0: close $csvnewfile: $!"; 
2

用grep

grep "^\w\{4\}\.\w\{4\}\.\w\{4\}\b" file 
+1

這是在命令行上,而不是在perl BTW。這就是'grep'的意義所在。如果你沒有現代的'grep',你可能需要'egrep'或像'^ [0-9a-zA-Z。] {14}'這樣的更老的正則表達式。 – Nathan 2010-02-23 00:54:30

+0

是的,在命令行上。我假設'grep'標籤是* nix grep,而不是Perl自己的。 – ghostdog74 2010-02-23 00:56:13

0
perl -ne 'print if /^\w{4}\.\w{4}\.\w{4}\b/' file > newfile.csv 
1

perlfaq5的答案How do I change, delete, or insert a line in a file, or append to the beginning of a file?


從一個文本文件中插入,更改或刪除線的基本思想包括閱讀並將文件打印到您想要進行更改的位置,進行更改,然後閱讀並打印文件的其餘部分樂。 Perl不提供對行的隨機訪問(特別是因爲記錄輸入分隔符$ /是可變的),雖然諸如Tie :: File之類的模塊可以僞造它。

一個Perl程序來完成這些任務需要打開一個文件,打印其行,然後關閉該文件的基本形式:

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

while(<$in>) 
    { 
    print $out $_; 
    } 

接近$出; 在該基本表單中,添加您需要插入,更改或刪除行的部分。

要在行首添加行,請在輸入打印現有行的循環之前打印這些行。

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC 

while(<$in>) 
    { 
    print $out $_; 
    } 

close $ out; 要更改現有行,請插入代碼以修改while循環內的行。在這種情況下,代碼將查找所有小寫版本的「perl」並將它們大寫。每一行都會發生,所以一定要在每一行都做到這一點!

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

print $out "# Add this line to the top\n"; 

while(<$in>) 
    { 
    s/\b(perl)\b/Perl/g; 
    print $out $_; 
    } 

close $ out; 要僅更改特定行,輸入行號$。是有用的。首先閱讀並打印您想要更改的行。接下來,閱讀您想要更改的單行,更改並打印它。之後,閱讀其餘的行並打印這些行:

while(<$in>) # print the lines before the change 
    { 
    print $out $_; 
    last if $. == 4; # line number before change 
    } 

my $line = <$in>; 
$line =~ s/\b(perl)\b/Perl/g; 
print $out $line; 

while(<$in>) # print the rest of the lines 
    { 
    print $out $_; 
    } 

要跳過行,請使用循環控制。本例中的下一個跳過註釋行,並且一旦遇到ENDDATA,最後一次停止所有處理。

while(<$in>) 
    { 
    next if /^\s+#/;    # skip comment lines 
    last if /^__(END|DATA)__$/; # stop at end of code marker 
    print $out $_; 
    } 

做同樣的事情來刪除一個特定的行,使用next來跳過你不想顯示在輸出中的行。只要

while(<$in>) 
    { 
    next unless $. % 5; 
    print $out $_; 
    } 

如果出於某種奇怪的原因,你真的想看到整個文件一次,而不是加工生產線,由線,您可以在思樂普它(如你:這個例如每第五行跳過可以容納在內存中的整個事情)!

open my $in, '<', $file  or die "Can't read old file: $!" 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

my @lines = do { local $/; <$in> }; # slurp! 

    # do your magic here 

print $out @lines; 

模塊如File :: Slurp的和領帶::文件可以提供幫助的了。但是,如果可以,請避免一次讀取整個文件。在這個過程完成之前,Perl不會將該內存返回給操作系統。

您還可以使用Perl one-liners來就地修改文件。以下內容將inFile.txt中的所有'Fred'更改爲'Barney',並用新內容覆蓋文件。使用-p開關,Perl將用-e指定的代碼包裝一個while循環,並且-i打開就地編輯。當前行在$ 。使用-p,Perl會在循環結束時自動打印$的值。有關更多詳細信息,請參閱perlrun。

perl -pi -e 's/Fred/Barney/' inFile.txt 

爲了inFile.txt的備份,給-ia文件擴展名補充:

perl -pi.bak -e 's/Fred/Barney/' inFile.txt 

要改變只有第五行,你可以添加一個測試檢查$,輸入線。數,則只有當測試通過執行操作:

perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt 

在一定行之前添加行,你可以添加一行的Perl打印$ _之前(或行!):

perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt 

你甚至可以在循環的末尾添加一行到文件的開頭,因爲當前行打印:

perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt 

已經在文件中,使用一個後插入一行-n開關。它就像-p,除了在循環結束時不打印$ _,所以你必須自己做。在這種情況下,首先打印$ _,然後打印要添加的行。

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt 

要刪除行,只打印所需的行。

perl -ni -e 'print unless /d/' inFile.txt 

    ... or ... 

perl -pi -e 'next unless /d/' inFile.txt 
相關問題