如何删除文件中的某些换行符

时间:2011-07-19 15:53:57

标签: perl replace line-breaks line-by-line

我有一个包含大约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);

但是有两个问题:

  • 它正确打印出连接线,但仍打印出第二行,例如

    + Fieldname2 - 内容 内容 -content

那么如何让脚本只输出连接线?

  • 它一次只能在两行上运行,而一些多行条目最多可以有四十行。

编辑2:我的问题是如何执行以下操作:

  1. 逐行读入文件并将其写入输出文件
  2. 当多行部分显示为一次性阅读并处理时,将\n-替换为 ,除非它属于给定的字段名称(例如Fieldname5
  3. 再次返回读取和写入每一行,直到出现另一个多行块
  4. 编辑3: 有效!我刚刚在开头添加了另一个条件:     用严格;     使用警告;

    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 个答案:

答案 0 :(得分:2)

假设只有以“ - ”开头的行是这些多行部分,你可以这样做......

# 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 $_;
    }
}

关于嵌入式子问题(“除了与最后一个字段有关的那些”之外),我需要更多关于文件格式的细节才能做到这一点。看起来像一个空白行将字段和内容集彼此分开,但在描述中并不是100%清楚。但是,上面的代码应该处理您在底部列出的要求。