Tengo un archivo .msg bastante grande formateado en el formato UIEE.
$ wc -l big_db.msg
8726593 big_db.msg
Básicamente, el archivo está compuesto por entradas de varias longitudes que se parecen a esto:
UR|1
AA|Condon, Richard
TI|Prizzi's Family
CN|Collectable- Good/Good
MT|FICTION
PU|G.P. Putnam & Sons
DP|1986
ED|First Printing.
BD|Hard Cover
NT|0399132104
KE|MAFIA
KE|FICTION
PR|44.9
XA|4
XB|1
XC|BO
XD|S
UR|10
AA|Gariepy, Henry
TI|Portraits of Perseverance
CN|Good/No Jacket
MT|SOLD
PU|Victor Books
DP|1989
BD|Mass Market Paperback
NT|1989 tpb g 100 meditations from the Book of Job "This book...help you
NT| persevere through the struggles of your life..."
KE|Bible
KE|religion
KE|Job
KE|meditations
PR|28.4
XA|4
XB|5
XC|BO
XD|S
Este es un ejemplo de dos entradas, separadas por una línea en blanco. Deseo dividir este archivo grande en archivos más pequeños sin dividir una entrada en dos archivos.
Cada entrada individual está separada por una nueva línea (una línea completamente en blanco) en el archivo. Deseo dividir este archivo de 8,7 millones de líneas en 15 archivos. Entiendo que split
existen herramientas como , pero no estoy muy seguro de cómo dividir el archivo, sino que solo se divide en una nueva línea para que una sola entrada no se divida en varios archivos.
text-processing
split
usuario2036066
fuente
fuente
csplit
También existe.|
(comoUR
,AA
,TI
) relevante para el recuento de los archivos, incluso el mismo para ser exactos?Respuestas:
Aquí hay una solución que podría funcionar:
Funciona permitiendo que el primero
sed
escriba elsed
guión del segundo . El segundosed
primero reúne todas las líneas de entrada hasta que encuentra una línea en blanco. Luego escribe todas las líneas de salida en un archivo. El primerosed
escribe un guión para el segundo y le indica dónde escribir su salida. En mi caso de prueba, ese script se veía así:Lo probé así:
Esto me proporcionó un archivo de 6000 líneas, que se veía así:
... repetido 1000 veces.
Después de ejecutar el script anterior:
SALIDA
fuente
Usando la sugerencia de
csplit
:División basada en números de línea
Ejemplo
Digamos que tengo un archivo con 1000 líneas.
da como resultado archivos como este:
Puede sortear la limitación estática de tener que especificar el número de repeticiones calculando previamente los números en función del número de líneas en su archivo en particular con anticipación.
División basada en líneas en blanco
Si, por otro lado, desea dividir simplemente un archivo en líneas en blanco contenidas en el archivo, puede usar esta versión de
split
:Ejemplo
Digamos que he agregado 4 líneas en blanco a lo
file.txt
anterior, y crea el archivofile2.txt
. Puede ver que se han agregado manualmente de la siguiente manera:Lo anterior muestra que los he agregado entre los números correspondientes dentro de mi archivo de muestra. Ahora cuando ejecuto el
csplit
comando:Puede ver que ahora tengo 4 archivos que se han dividido según la línea en blanco:
Referencias
fuente
Si no le importan las órdenes de los registros, puede hacer lo siguiente:
De lo contrario, primero necesitaría obtener el número de registros, para saber cuántos poner en cada archivo de salida:
fuente
file.in
yfile.out
?Si está buscando dividir solo al final de una línea, debería poder hacerlo con la
-l
opción parasplit
.Si está buscando dividir en una línea en blanco (
\n\n
), así es como lo haría en ksh. No lo he probado, y probablemente no sea lo ideal, pero algo en esta línea funcionaría:fuente
\n\n
, creo.\n\n
, sino más bien no dividirse en medio de una línea. Él está llamando a una nueva línea una línea en blanco.Tratar
awk
fuente
Si no le importa el orden de los registros, pero le interesa obtener una cierta cantidad de archivos de salida, la respuesta de Stephane es el camino que seguiría. Pero tengo la sensación de que podría importarle más especificar un tamaño que cada archivo de salida no debería exceder. En realidad, eso lo hace más fácil porque puede leer su archivo de entrada y recopilar registros hasta alcanzar ese tamaño, y luego comenzar un nuevo archivo de salida. Si eso funciona para usted, la mayoría de los lenguajes de programación pueden manejar su tarea con un script corto. Aquí hay una implementación awk:
Ponga esto en un archivo, por ejemplo
program.awk
, y ejecúteloawk -v maxlen=10000 -f program.awk big_db.msg
donde el valor demaxlen
sea la mayor cantidad de bytes que desee en cualquier archivo. Utilizará 500k por defecto.Si desea obtener un número determinado de archivos, probablemente la forma más fácil es dividir el tamaño de su archivo de entrada por el número de archivos que desea y luego agregar un poco a ese número para obtener
maxlen
. Por ejemplo, para obtener 15 archivos de sus 8726593 bytes, divídalos por 15 para obtener 581773, y agregue algunos, así que tal vez démaxlen=590000
omaxlen=600000
. Si desea hacer esto repetidamente, sería posible configurar el programa para hacerlo.fuente