2011-07-19 63 views
2

我有一個包含約70,000條記錄,其大致結構像這樣的文件:解決:如何把刪除某些換行符在文件中

01499  1000642 4520101000900000 
...more numbers... 
104000900169 
+Fieldname1 
-Content 
+Fieldname2 
-Content 
-Content 
-Content 
+Fieldname3 
-Content 
-Content 
+Fieldname4 
-Content 
+Fieldname5 
-Content 
-Content 
-Content 
-Content 
-Content 
-Content 

01473  1000642 4520101000900000 
...more numbers... 

編輯1:每記錄由此開始與一列數字並以空行結束。在此空白行之前,大多數記錄具有+Fieldname5和一個或多個-Content行。

我想這樣做的是所有多行條目合併成一條線,而用空格代替領先負字符的情況除外那些與最後一個字段(即Fieldname5在這種情況下)。

它應該是這樣的:

01499  1000642 4520101000900000 
...more numbers... 
104000900169 
+Fieldname1 
-Content 
+Fieldname2 
-Content Content Content 
+Fieldname3 
-Content Content 
+Fieldname4 
-Content 
+Fieldname5 
-Content 
-Content 
-Content 
-Content 
-Content 
-Content 

01473  1000642 4520101000900000 
...more numbers... 

什麼,我現在是這樣(改編自this answer):

use strict; 
use warnings; 

our $input = "export.txt"; 
our $output = "export2.txt"; 

open our $in, "<$input" or die "$!\n"; 
open our $out, ">$output" or die "$!\n"; 

my $this_line = ""; 
my $new = ""; 

while(<$in>) { 
    my $last_line = $this_line; 
    $this_line = $_; 

    # if both $last_line and $this_line start with a "-" do the following: 
    if ($last_line =~ /^-.+/ && $this_line =~ /^-.+/) { 

     #remove \n from $last_line 
     chomp $last_line; 

     #remove leading "-" from $this_line 
     $this_line =~ s/^-//; 

     #join both lines and print them to the file 
     $new = join(' ', $last_line,$this_line); 
     print $out $new; 
     } else { 
     print $out $last_line; 
      } 
    } 
close ($in); 
close ($out); 

,但有2個問題是:

  • 它正確打印出連接的行,但仍然打印出第二行,例如

    + Fieldname2 -content內容 內容 -content

那麼,怎樣才能讓我的腳本只輸出連接線?

  • 它一次只能在兩條線上工作,而一些多線條目有多達四十條線。

編輯2:我的問題是這樣如何做到以下幾點:通過線

  1. 讀取文件中的行,並將其寫入到輸出文件
  2. 當多管路段出現讀取並一次處理它,替換\n-,除非它屬於給定的字段名稱(例如Fieldname5)。
  3. 返回讀取和寫入一次的每一行,直到另一個多行數據塊出現

編輯3: 它的工作!我剛剛在開頭添加了另一個條件: 使用strict; 使用警告;

our $input = "export.txt"; 
our $output = "export2.txt"; 

open our $in, "<$input" or die "Kann '$input' nicht finden: $!\n"; 
open our $out, ">$output" or die "Kann '$output' nicht erstellen: $!\n"; 


my $insideMultiline = 0; 
my $multilineBuffer = ""; 
my $exception = 0;     # variable indicating whether the current multiline-block is a "special" or not 

LINE: 
while (<$in>) { 
    if (/^\+Fieldname5/) {   # if line starts with +Fieldname5, set $exception to "1" 
     $exception = 1; 
    } 
    elsif (/^\s/) {     # if line starts with a space, set $exception to "0" 
     $exception = "0"; 
    } 
    if ($exception == 0 && /^-/) { # if $exception is "0" AND the line starts with "-", do the following 
     chomp; 
     if ($insideMultiline) { 
      s/^-/ /; 
      $multilineBuffer .= $_; 
     } 
     else { 
      $insideMultiline = 1; 
      $multilineBuffer = $_; 
     } 
     next LINE; 
    } 
    else { 
     if ($insideMultiline) { 
      print $out "$multilineBuffer\n"; 
      $insideMultiline = 0; 
      $multilineBuffer = ""; 
     } 
     print $out $_; 
     } 
} 

close ($in); 
close ($out); 

非常感謝!

回答

1

假設只有以「 - 」開頭的行是這些多行部分,您可以這樣做......

# Open $in and $out as in your original code... 

my $insideMultiline = 0; 
my $multilineBuffer = ""; 

LINE: 
while (<$in>) { 
    if (/^-/) { 
     chomp; 
     if ($insideMultiline) { 
      s/^-/ /; 
      $multilineBuffer .= $_; 
     } 
     else { 
      $insideMultiline = 1; 
      $multilineBuffer = $_; 
     } 
     next LINE; 
    } 
    else { 
     if ($insideMultiline) { 
      print $out "$multilineBuffer\n"; 
      $insideMultiline = 0; 
      $multilineBuffer = ""; 
     } 
     print $out $_; 
    } 
} 

至於嵌入式subquestion(「除非屬於上一次場那些」),我需要的文件格式更詳細地能夠做到這一點。它看起來像一條空白的線將字段和內容集合彼此分開,但在描述中不是100%清楚。儘管如此,上面的代碼應該能夠滿足你在底部的需求。