3

おおよそ次のような構造の約 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...

EDIT 1: したがって、すべてのレコードは数字の列で始まり、空白行で終わります。ほとんどのレコードには、この空白行の前に+Fieldname5と 1 つ以上の-Content行があります。

私がやりたいことは、最後のフィールド (この場合は Fieldname5) に関連するものを除いて、先頭のマイナス文字をスペースに置き換えながら、すべての複数行エントリを 1 行にマージすることです。

次のようになります。

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つの問題があります:

  • 結合された行を正しく印刷しますが、それでも2行目を印刷します。

    +Fieldname2 -コンテンツ コンテンツ コンテンツ -コンテンツ

では、スクリプトが結合された行のみを出力するようにするにはどうすればよいでしょうか?

  • 一度に 2 行でしか機能しませんが、複数行のエントリの中には最大 40 行まであるものもあります。

編集2:私の質問は、次のことを行う方法です:

  1. ファイルを 1 行ずつ読み込み、出力ファイルに書き込みます
  2. 複数行のセクションが表示された場合は、指定されたフィールド名 (例: ) に属している場合を除き\n-、一度に読み取って処理し、 に置き換えます。Fieldname5
  3. 別の複数行ブロックが表示されるまで、各行の読み取りと書き込みに戻ります

編集3: うまくいきました!最初に別の条件を追加しました: use 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);
4

1 に答える 1

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% 明確ではありません。ただし、上記のコードは、下部に示した要件を処理する必要があります。

于 2011-07-20T00:14:53.630 に答える