Как поставить удалить определенные разрывы строк в файле - PullRequest
3 голосов
/ 19 июля 2011

У меня есть файл, который содержит около 70000 записей, который примерно так структурирован:

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...

что ятеперь есть это (адаптировано из этот ответ ):

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 Content -Content

Так как я могу сделать так, чтобы скрипт выводил только объединенную строку?

  • Работает только на двух строках одновременно, в то время как некоторые многострочные записи имеют до сорока строк.

РЕДАКТИРОВАТЬ 2: Таким образом, мой вопрос состоит в том, как сделать следующее:

  1. Считать файл за строкой и записать его в выводfile
  2. Когда появляется многострочный раздел, прочитайте и обработайте его за один раз, заменив \n- на , за исключением случаев, когда он принадлежит данному имени поля (например, Fieldname5).
  3. Вернуться к чтению и записи каждой строки снова, пока не появится другой многострочный блок

РЕДАКТИРОВАТЬ 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 Ответ

2 голосов
/ 20 июля 2011

Предполагая, что единственными строками, начинающимися с "-", являются эти многострочные секции, вы можете сделать это ...

# 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% ясно в описании. Код выше должен соответствовать требованиям, которые вы изложили внизу.

...