2012-06-08 160 views
2

我需要將文件拆分爲不同的文件。Perl:如何分割文件?

〔實施例(原始文件):

*****3123123*****RAW 
text1 
text2 
*****2312354***RAW 
text3 

希望的輸出:

[FILE1.TXT]

*****3123123*****RAW  
text1 
text2 

[FILE2.TXT]

*****312312354***RAW 
text3 

我試圖使用拆分,但我總是這樣我額外的空白字符到數組

open FILE, "<file"; 
@file= <FILE>; 
close FILE; 
@lines = split (/(RAW\n)/, "@file"); 
foreach $value (@lines) { 
    if ($value =~ /[a-z]|[A-Z]|[1-9]/) { 
    print ("$value\n"); 
    } 
} 

輸出:

*****3123123*****RAW 

text1 
text2 

*****312312354***RAW 

text3 

編輯:如果我使用打印( 「$值」),而不是打印( 「$值\ n」),這是輸出(前值注意1個額外的空間:

*****3123123*****RAW 
text1 
text2 

*****12354***RAW 
text3 
+1

是不是隻是當你分裂時,它不會刪除換行符,所以當你添加'print(「$ value \ n」)'時,你會添加一個額外的換行符。這就是爲什麼它看起來有多餘的空白。 –

+0

沒有\ n我在每個值的開始處得到1個額外的空白區域。 – user1444482

+0

額外的空間是因爲您將'@ file'插入單個字符串中,默認情況下會在元素之間插入空格字符。通常一行一行讀取文件通常會更好,除非它非常小,但如果你堅持一次讀取所有文件,你可以寫'@lines = split(/(RAW \ n)/,加入'',@ file'或我的$ data = do {local $ /;; }; @lines = split(/(RAW \ n)/,$ data; – Borodin

回答

1

該程序從RAW行中提取十進制數,並用它來命名輸出文件。它期望輸入文件名作爲命令行上的參數。

use strict; 
use warnings; 

@ARGV or die "Input file required as command-line parameter\n"; 

my $out; 

while (<>) { 
    if (/(\d+)\*+RAW$/) { 
    open $out, '>', "$1.out" or die $!; 
    select $out; 
    } 
    print $_ if $out; 
} 
+0

非常感謝你。 – user1444482

2

你可能會與線明智的IO做的更好:

my $id = 0; 
my $FILE = undef; 

while (<>) { 
    if (/RAW/) { 
     close $FILE if defined $FILE; 
     $id++; 
     my $path = "File$id.txt"; 
     open $FILE, '>', $path or die "Could not open $path: $!"; 
    } 
    print $FILE $_ if defined $FILE; 
} 
close $FILE if defined $FILE; 

從我的一個腳本中複製並修改,這些腳本將郵箱文件分爲每個郵件一個文件。如果第一行不匹配,您將不得不修改腳本/RAW/

+0

試圖運行腳本,但沒有任何反應。但從來沒有完成,所以我必須Ctrl-C它 – user1444482

+1

@ user1444482:這個解決方案工作正常,它需要像我的命令行輸入文件如果你不提供一個它會掛起等待輸入鍵盤。 – Borodin

+0

你爲什麼做這個社區Wiki? –

0

這就是我想到的。我不禁感到這是在重新發明輪子。

#!usr/bin/perl 
my $fi, $fi2; 
my $line; 
my $i; 
my @lines; 
my @filenameparts; 
my $filename = "file_1.txt"; 

open($fi, "< original.txt"); 
@lines = <$fi>; 
open ($fi2, " > $filename"); 

foreach (@lines) 
{ 
if (($i > 0) and $_ =~ /RAW/) 
{ 
    @filenameparts = split("_", $filename); 
    foreach (@filenameparts) 
    { 
     print "Woooo".$_; 
    } 
    @filenameparts[1] = substr(@filenameparts[1], 0, @filenameparts[1].length() - 5); 
    @filenameparts[1] = ($filenameparts[1] + 1); 
    $filename = @filenameparts[0]."_"[email protected][1].".txt"; 
    print $filename; 
    close($fi2); 
    open ($fi2, " > $filename"); 
    $i = 0; 
    print $fi2 $_; 

} 
else 
{ 
    print $fi2 $_; 
} 
$i++; 

} 
+2

你必須養成在Perl程序的頂部添加'use strict'和'use warnings'的習慣。這會顯示出很多與編程有關的問題,這些問題並不明顯。你應該還記得你編寫的是Perl,而不是Java,JavaScript或C++ - 無論你來自哪裏 - 作爲@filenameparts [1] .length()'不會獲得數組中第二個字符串的長度,它把第二個字符串和'$ _'的長度連接起來,它們並不完全相同。 – Borodin

+0

我衷心同意你的觀點,即我的Perl編程很差勁。 – PinkElephantsOnParade

+0

只是想幫助你提高:)順便說一句,我的解決方案比daxim的高爾夫:P – Borodin

2
use strictures; 
use File::Slurp qw(read_file write_file); 
my $raw = read_file('raw.txt', binmode => ':raw'); 
my $header = qr/^ (?= [*]+ [0-9]+ [*]+ RAW\n)/msx; 
my @chunks = split $header, $raw; 
# (
#  "*****3123123*****RAW\ntext1\ntext2\n", 
#  "*****2312354***RAW\ntext3" 
#) 
for my $i ([email protected]) { 
    write_file("File$i.txt", {binmode => ':raw'}, $chunks[$i-1]); 
} 
+0

Woah你一定會贏得Perl高爾夫球heh – PinkElephantsOnParade

+2

這甚至不是高爾夫球,這是一個經驗豐富的程序員寫的一個簡單直接的Perl。沒有關於它的晦澀難懂的知識,只是**在適當的時候記住內置插件**的功能,例如[split](http://p3rl.org/split)和**使用CPAN庫**。 – daxim

+0

爲什麼'binmode'? – Borodin

0

如果你想和你做的代碼,然後簡單地只是print ("$value");更換您的行print ("$value\n");,你已經有了它...

或者print之前刪除\nchomp($value);和留在輸出print ("$value\n");