Divida un archivo en varios archivos basados ​​en el delimitador

Tengo un archivo con -| como delimitador después de cada sección … necesita crear archivos separados para cada sección usando Unix.

ejemplo de archivo de entrada

 wertretr ewretrtret 1212132323 000232 -| ereteertetet 232434234 erewesdfsfsfs 0234342343 -| jdhg3875jdfsgfd sjdhfdbfjds 347674657435 -| 

Resultado esperado en el archivo 1

 wertretr ewretrtret 1212132323 000232 -| 

Resultado esperado en el archivo 2

 ereteertetet 232434234 erewesdfsfsfs 0234342343 -| 

Resultado esperado en el archivo 3

 jdhg3875jdfsgfd sjdhfdbfjds 347674657435 -| 

Un trazador de líneas, sin progtwigción. (excepto la expresión regular, etc.)

 csplit --digits=2 --quiet --prefix=outfile infile "/-|/+1" "{*}" 
 awk '{print $0 " -|"> "file" NR}' RS='-\\|' input-file 

Debian tiene csplit , pero no sé si eso es común a todas / most / otras distribuciones. Sin embargo, si no es así, no debería ser demasiado difícil rastrear la fuente y comstackrla …

Resolví un problema ligeramente diferente, donde el archivo contiene una línea con el nombre donde debería ir el texto que sigue. Este código perl me funciona:

 #!/path/to/perl -w #comment the line below for UNIX systems use Win32::Clipboard; # Get command line flags #print ($#ARGV, "\n"); if($#ARGV == 0) { print STDERR "usage: ncsplit.pl --mff -- filename.txt [...] \n\nNote that no space is allowed between the '--' and the related parameter.\n\nThe mff is found on a line followed by a filename. All of the contents of filename.txt are written to that file until another mff is found.\n"; exit; } # this package sets the ARGV count variable to -1; use Getopt::Long; my $mff = ""; GetOptions('mff' => \$mff); # set a default $mff variable if ($mff eq "") {$mff = "-#-"}; print ("using file switch=", $mff, "\n\n"); while($_ = shift @ARGV) { if(-f "$_") { push @filelist, $_; } } # Could be more than one file name on the command line, # but this version throws away the subsequent ones. $readfile = $filelist[0]; open SOURCEFILE, "< $readfile" or die "File not found...\n\n"; #print SOURCEFILE; while () { /^$mff (.*$)/o; $outname = $1; # print $outname; # print "right is: $1 \n"; if (/^$mff /) { open OUTFILE, ">$outname" ; print "opened $outname\n"; } else {print OUTFILE "$_"}; } 

También puedes usar awk. No estoy muy familiarizado con awk, pero lo siguiente parece funcionar para mí. Se generó part1.txt, part2.txt, part3.txt y part4.txt. Tenga en cuenta que el último archivo partn.txt que esto genera está vacío. No estoy seguro de cómo solucionarlo, pero estoy seguro de que podría hacerse con un pequeño ajuste. ¿Alguna sugerencia a alguien?

awk_pattern file:

 BEGIN{ fn = "part1.txt"; n = 1 } { print > fn if (substr($0,1,2) == "-|") { close (fn) n++ fn = "part" n ".txt" } } 

comando bash:

awk -f awk_pattern input.file

Aquí hay una secuencia de comandos de Python 3 que divide un archivo en varios archivos en función de un nombre de archivo proporcionado por los delimitadores. Ejemplo de archivo de entrada:

 # Ignored ######## FILTER BEGIN foo.conf This goes in foo.conf. ######## FILTER END # Ignored ######## FILTER BEGIN bar.conf This goes in bar.conf. ######## FILTER END 

Aquí está el guión:

 #!/usr/bin/env python3 import os import argparse # global settings start_delimiter = '######## FILTER BEGIN' end_delimiter = '######## FILTER END' # parse command line arguments parser = argparse.ArgumentParser() parser.add_argument("-i", "--input-file", required=True, help="input filename") parser.add_argument("-o", "--output-dir", required=True, help="output directory") args = parser.parse_args() # read the input file with open(args.input_file, 'r') as input_file: input_data = input_file.read() # iterate through the input data by line input_lines = input_data.splitlines() while input_lines: # discard lines until the next start delimiter while input_lines and not input_lines[0].startswith(start_delimiter): input_lines.pop(0) # corner case: no delimiter found and no more lines left if not input_lines: break # extract the output filename from the start delimiter output_filename = input_lines.pop(0).replace(start_delimiter, "").strip() output_path = os.path.join(args.output_dir, output_filename) # open the output file print("extracting file: {0}".format(output_path)) with open(output_path, 'w') as output_file: # while we have lines left and they don't match the end delimiter while input_lines and not input_lines[0].startswith(end_delimiter): output_file.write("{0}\n".format(input_lines.pop(0))) # remove end delimiter if present if not input_lines: input_lines.pop(0) 

Finalmente, así es como lo ejecutas:

 $ python3 script.py -i input-file.txt -o ./output-folder/ 
 cat file| ( I=0; echo -n "">file0; while read line; do echo $line >> file$I; if [ "$line" == '-|' ]; then I=$[I+1]; echo -n "" > file$I; fi; done ) 

y la versión formateada:

 #!/bin/bash cat FILE | ( I=0; echo -n"">file0; while read line; do echo $line >> file$I; if [ "$line" == '-|' ]; then I=$[I+1]; echo -n "" > file$I; fi; done; ) 

Este es el tipo de problema que escribí contexto dividido para: http://stromberg.dnsalias.org/~strombrg/context-split.html

 $ ./context-split -h usage: ./context-split [-s separator] [-n name] [-z length] -s specifies what regex should separate output files -n specifies how output files are named (default: numeric -z specifies how long numbered filenames (if any) should be -i include line containing separator in output files operations are always performed on stdin 

El siguiente comando funciona para mí. Espero eso ayude. bash awk 'BEGIN{file = 0; filename = "output_" file ".txt"} /-|/ {getline; file ++; filename = "output_" file ".txt"}{print $0 > filename}' input awk 'BEGIN{file = 0; filename = "output_" file ".txt"} /-|/ {getline; file ++; filename = "output_" file ".txt"}{print $0 > filename}' input

Usa csplit si lo tienes.

Si no lo hace, pero tiene Python … no use Perl.

Suponiendo que su archivo de muestra se llama ” samplein “:

 $ python -c "import sys for i, c in enumerate(sys.stdin.read().split('-|')): open(f'out{i}', 'w').write(c)" < samplein 

Si tiene Python 3.5 o una versión anterior, no puede usar cadenas f:

 $ python -c "import sys for i, c in enumerate(sys.stdin.read().split('-|')): open('out' + str(i), 'w').write(c)" < samplein 

y ahora:

 $ ls out* out0 out1 out2 out3 

Aquí hay un código perl que hará la cosa

 #!/usr/bin/perl open(FI,"file.txt") or die "Input file not found"; $cur=0; open(FO,">res.$cur.txt") or die "Cannot open output file $cur"; while() { print FO $_; if(/^-\|/) { close(FO); $cur++; open(FO,">res.$cur.txt") or die "Cannot open output file $cur" } } close(FO);