son que programacion los delimitadores delimitador file unix split chunking

file - que - archivo dividido en la enésima aparición de delimitador



que es un delimitador en programacion (3)

¿Hay un trazador de líneas para dividir un archivo de texto en pedazos / trozos después de cada enésima ocurrencia de un delimitador?

ejemplo: el delimitador a continuación es "+"

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

Hay varios millones de entradas, por lo que dividir en cada aparición de delimitador "+" es una mala idea. Quiero dividir, por ejemplo, cada instancia 50,000 del delimitador "+".

Los comandos de Unix "split" y "csplit" simplemente no parecen hacer esto ...


No es muy difícil hacerlo en Perl si no puedes encontrar una alternativa adecuada (y funcionará bastante bien):

#!/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;

Eso está lejos de ser un trazador de líneas; No estoy seguro de si eso es un mérito o no. Los elementos que deben configurarse se agrupan y pueden configurarse mediante opciones de línea de comando, por ejemplo. Podría terminar con un archivo vacío; usted podría detectar eso y eliminarlo si es necesario. Necesitarías un segundo contador; el existente es un "contador de coincidencias" pero también necesitarías un contador de línea, y si el contador de línea fuera cero en ese momento, eliminarías el último archivo. También necesitarías el nombre para poder eliminarlo ... difícilmente, pero no difícil.

Dar la entrada (básicamente dos copias de sus datos de muestra), la salida de repsplit.pl (repetir división) fue como se muestra:

$ 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 + $


Usando perl y + como separador de entrada en un "trazador de líneas" conciso:

Si desea hacer $_ > newprefix.part.$c como se indica en su comentario:

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

Doc


Usando awk puedes:

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

Actualizar:

Para no incluir el delimitador, intente esto:

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

La next palabra clave hace que awk pare las reglas de procesamiento para este registro y avance a la siguiente (línea). También cambié el >> a > ya que si lo ejecuta más de una vez, probablemente no quiera agregar los viejos archivos de fragmentos.