ブロックで構成されたファイルに集計されたデータがあります。
---- BLOCK ONE ----
some data
another data
more data
more data
-------------------
---- BLOCK two ----
some data
another data
-------------------
---- BLOCK THREE ----
some data
another data
more data
-------------------
など。総ブロック数は約2000個です。
項目(データ行)が4つ未満のブロックを抽出する必要があります。これを行う方法を知ってください(Perlが好ましいです)。
ベストアンサー1
$ perl -00 -F'\n' -n -e '
$file = shift @F;
pop @F;
if (@F < 4) {
$file =~ s/^---- | ----//g;
open(OUT, ">", $file.".txt");
print OUT join("\n", @F), "\n"
}' input.txt
-00
このperl 1行ステートメントは、短絡モードで入力を読み込み(複数の改行で区切られている)、-F
自動的に改行の入力を@ F配列に分割し、-n
入力を印刷せずに自動的に読み取るために使用されます(に似ていますsed -n
)。
まず、Shiftを使用して@Fの最初の要素を$ file変数に入れます。その後、pop @ Fは最後の要素(-------------------
)を削除します。残りの要素が4つ未満の場合は、$ fileから合計を----
削除し、書き込み用に ----
"$ file.txt"を開き、配列の残りの部分をそのファイルに印刷します。
これらのファイル名が気に入らない場合は、演算子を使用する$file = sprintf "file%04i.txt", ++$counter
代わりにブロック内でカウンタ変数を増やすなど、他の方法を使用できます。if
s///
---- BLOCK...
ただし、ヘッダーとフッターを維持するには、------*
行をに置き換えてテストをに変更します。shift
pop
$file = $F[0]
if
if (@F < 6)
出力例(tail
ファイル名印刷用):
$ tail BLOCK*.txt
==> BLOCK THREE.txt <==
some data
another data
more data
==> BLOCK two.txt <==
some data
another data
スタンドアロンスクリプトと同じですが、カウンタを使用してファイル名を生成します。
$ cat split-blocks.pl
#!/usr/bin/perl
use strict;
my $counter;
$/='';
while(<<>>) {
my @lines = split /\n/;
my $file = shift @lines;
pop @lines;
if (@lines < 4) {
$file = sprintf 'file%04i.txt', ++$counter
open(OUT, ">", $file) || die "couldn't open $file for write: $!\n";
print OUT join("\n", @lines), "\n"
}
};
$ ./split-blocks.pl input.txt
$ tail file*
==> file0001.txt <==
some data
another data
==> file0002.txt <==
some data
another data
more data