2011-07-19 44 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%清楚。尽管如此,上面的代码应该能够满足你在底部的需求。