linux - unir - split unix
Divida un archivo en varios archivos basados en el delimitador (11)
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
-|
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(<FI>)
{
print FO $_;
if(/^-/|/)
{
close(FO);
$cur++;
open(FO,">res.$cur.txt") or die "Cannot open output file $cur"
}
}
close(FO);
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/
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 compilarla ...
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
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
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 (<SOURCEFILE>) {
/^$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
Un trazador de líneas, sin programación. (excepto la expresión regular, etc.)
csplit --digits=2 --quiet --prefix=outfile infile "/-|/+1" "{*}"
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
awk ''{print $0 " -|"> "file" NR}'' RS=''-//|'' input-file
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;
)