13

区切り文字がN回出現するたびに、テキストファイルを断片/チャンクに分割するワンライナーはありますか?

例:以下の区切り文字は「+」です

entry 1
some more
+
entry 2
some more
even more
+
entry 3
some more
+
entry 4
some more
+
...

エントリは数百万あるため、区切り文字「+」が出現するたびに分割することはお勧めできません。たとえば、区切り文字「+」の50,000番目のインスタンスごとに分割したいと思います。

Unixコマンドの「split」と「csplit」はこれを行わないようです...

4

3 に答える 3

13

あなたを使用awkすることができます:

awk '/^\+$/ { delim++ } { file = sprintf("chunk%s.txt", int(delim / 50000)); print >> file; }' < input.txt 

アップデート:

区切り文字を含めないようにするには、次のことを試してください。

awk '/^\+$/ { if(++delim % 50000 == 0) { next } } { file = sprintf("chunk%s.txt", int(delim / 50000)); print > file; }' < input.txt 

このnextキーワードにより、awkはこのレコードの処理ルールを停止し、次の(行)に進みます。>>また、をに変更しました>。これは、複数回実行する場合、古いチャンクファイルを追加したくない場合があるためです。

于 2013-03-21T23:41:59.400 に答える
1

適切な代替手段が見つからない場合、Perl で行うのはそれほど難しくありません (そして、かなりうまく機能します)。

#!/usr/bin/env perl
use strict;
use warnings;

# Configuration items - could be set by argument handling
my $prefix = "rs.";     # File prefix
my $number = 1;         # First file number
my $width  = 4;         # Number of digits to use in file name
my $rx     = qr/^\+$/;  # Match regex
my $limit  = 3;         # 50,000 in real case
my $quiet  = 0;         # Set to 1 to suppress file names

sub next_file
{
    my $name = sprintf("%s%.*d", $prefix, $width, $number++);
    open my $fh, '>', $name or die "Failed to open $name for writing";
    print "$name\n" unless $quiet;
    return $fh;
}

my $fh = next_file;  # Output file handle
my $counter = 0;     # Match counter
while (<>)
{
    print $fh $_;
    $counter++ if (m/$rx/);
    if ($counter >= $limit)
    {
        close $fh;
        $fh = next_file;
        $counter = 0;
    }
}
close $fh;

それはワンライナーではありません。それがメリットかどうかはわかりません。構成する必要がある項目はグループ化されており、コマンド ライン オプションなどを使用して設定できます。空のファイルになってしまう可能性があります。それを見つけて、必要に応じて削除できます。2 つ目のカウンターが必要です。既存のものは「一致カウンター」ですが、行カウンターも必要です。行カウンターがゼロの場合は、最後のファイルを削除します。また、名前を削除できるようにする必要があります...手間がかかりますが、難しくはありません。

入力 (基本的にはサンプル データの 2 つのコピー) を与えると、repsplit.pl(反復分割) からの出力は次のようになります。

$ perl repsplit.pl data
rs.0001
rs.0002
rs.0003
$ cat data
entry 1
some more
+
entry 2
some more
even more
+
entry 3
some more
+
entry 4
some more
+
entry 1
some more
+
entry 2
some more
even more
+
entry 3
some more
+
entry 4
some more
+
$ cat rs.0001
entry 1
some more
+
entry 2
some more
even more
+
entry 3
some more
+
$ cat rs.0002
entry 4
some more
+
entry 1
some more
+
entry 2
some more
even more
+
$ cat rs.0003
entry 3
some more
+
entry 4
some more
+
$
于 2013-03-21T23:49:00.890 に答える
0

簡潔な「ワンライナー」で入力セパレータとしてを使用する:+

$_ > newprefix.part.$cコメントに記載されているようにしたい場合:

$ limit=50000 perl -053 -Mautodie -lne '
    BEGIN{$\=""}
    $count++;
    if ($count >= $ENV{limit}) {
        open my $fh, ">", "newprefix.part.$c";
        print $fh $_;
        close $fh;
    }
' file.txt

$ ls -l newprefix.part.*

ドク

于 2013-03-21T23:32:56.880 に答える