Tengo un archivo de texto llamado entry.txt
que contiene lo siguiente:
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
Me gustaría que dividirlo en tres archivos de texto: entry1.txt
, entry2.txt
, entry3.txt
. Sus contenidos son los siguientes.
entry1.txt :
[ entry1 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3633 3634 3636 3690 3691 3693 3766
3767 3769 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5628 5629 5631
entry2.txt :
[ entry2 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4526
4527 4529 4583 4584 4586 4773 4774 4776 5153 5154
5156 5628 5629 5631
entry3.txt :
[ entry3 ]
1239 1240 1242 1391 1392 1394 1486 1487 1489 1600
1601 1603 1657 1658 1660 2075 2076 2078 2322 2323
2325 2740 2741 2743 3082 3083 3085 3291 3292 3294
3481 3482 3484 3690 3691 3693 3766 3767 3769 4241
4242 4244 4526 4527 4529 4583 4584 4586 4773 4774
4776 5153 5154 5156 5495 5496 5498 5628 5629 5631
En otras palabras, el [
carácter indica que debe comenzar un nuevo archivo. Las entradas ( [ entry*]
donde *
es un número entero) siempre están en orden numérico y son números enteros consecutivos que comienzan de 1 a N (en mi archivo de entrada real, N = 200001).
¿Hay alguna manera de lograr la división automática de archivos de texto en bash? Mi entrada real en entry.txt
realidad contiene 200,001 entradas.
fuente
match
la entrada:/^\[/ { name=$2 }
debería ser suficiente.[ blahblah blah blah ]
en mi respuesta.FS
, por ejemplo-F '\\[ | \\]'
.#S x
, donde x es un número de 1, 2 o 3 dígitos. Solo guardarlos en x.dat sería suficiente. Lo intenté:gawk '/^#S/{match($0, / [0-9]* /, k)} {print >k[1]".dat" }' myFile.txt
y algunas variaciones de eso.gawk '/^#S/{match($0, /^#S (\s+?)([0-9]+)(\s+?)/, k)} {print >k[2]".txt" }' test.txt
hecho el truco. Sin2
embargo, no entiendo muy bien el número de matriz .Con csplit de GNU coreutils (Linux no incorporado, Cygwin):
Terminará con un archivo vacío adicional
entry0.txt
(que contiene la parte anterior al primer encabezado).El estándar csplit carece del
{*}
repetidor indefinido y la-b
opción de especificar el formato del sufijo, por lo que en otros sistemas tendrá que contar primero el número de secciones y luego cambiar el nombre de los archivos de salida.fuente
En perl se puede hacer mucho más simple:
fuente
Aquí hay un breve awk one-liner:
¿Como funciona esto?
/^\[/
coincide con las líneas que comienzan con un corchete izquierdo y{ofn=$2 ".txt"}
establece una variable en la segunda palabra delimitada por espacios en blanco como nuestro nombre de archivo de salida. Luego,ofn
es una condición que se evalúa como verdadera si la variable está establecida (lo que hace que se ignoren las líneas antes de su primer encabezado){print > ofn}
redirige la línea actual al archivo especificado.Tenga en cuenta que todos los espacios en este script awk se pueden eliminar, si la compacidad lo hace feliz.
Tenga en cuenta también que el script anterior realmente necesita que los encabezados de sección tengan espacios alrededor y no dentro de ellos. Si quisieras poder manejar encabezados de sección como
[foo]
y[ this that ]
, necesitarías un poco más de código:Esto utiliza la
sub()
función de awk para quitar espacios iniciales y finales de corchetes, más espacios en blanco. Tenga en cuenta que según el comportamiento awk estándar, esto colapsará los espacios en blanco (el separador de campo) en un solo espacio ([ this that ]
es decir, se guarda en"this that.txt"
). Si es importante mantener el espacio en blanco original en los nombres de los archivos de salida, puede experimentar configurando FS.fuente
Se puede hacer desde la línea de comando en python como:
fuente
Esta es una forma un tanto cruda, pero fácil de entender: utilícela
grep -l '[ entry ]' FILENAME
para dividir los números de línea en [entrada]. Usa una combinación de cabeza y cola para obtener las piezas correctas.Como dije; No es bonito, pero es fácil de comprender.
fuente
¿Qué pasa con el uso de awk con
[
como separador de registros y el espacio como separador de campo? Esto nos proporciona fácilmente los datos que se colocarán en el archivo, ya$0
que debe volver a colocar el encabezado eliminado[
y el nombre de archivo como$1
. Entonces solo tenemos que manejar el caso especial del primer registro que está vacío. Esto nos da:fuente
La respuesta de terdon me funciona, pero necesitaba usar gawk, no awk. El manual de gawk (busque 'match (') explica que el argumento de matriz en match () es una extensión de gawk. Tal vez depende de su instalación de Linux y sus versiones awk / nawk / gawk, pero en mi máquina Ubuntu solo gawk ejecutó la excelente terdon responder:
fuente
Aquí hay una solución perl. Este script detecta las
[ entryN ]
líneas y cambia el archivo de salida en consecuencia, pero no valida, analiza o procesa los datos en cada sección, solo imprime la línea de entrada en el archivo de salida.fuente
Hola, escribí este sencillo script usando ruby para resolver tu problema
puedes usarlo de esta manera:
Lo he probado y funciona bien.
fuente
Prefiero la
csplit
opción, pero como alternativa, aquí hay una solución awk de GNU:parse.awk
Ejecútelo así:
fuente
RT
variable parece ser específica de gawk. Esta solución no funciona para mí usando el awk de FreeBSD.