¿Cómo dividir un archivo grande en dos partes, en un patrón?
Dado un ejemplo file.txt
:
ABC
EFG
XYZ
HIJ
KNL
Quiero dividir este archivo en XYZ
tal que file1
contenga líneas hasta XYZ
y el resto de las líneas file2
.
text-processing
sed
awk
split
d.putto
fuente
fuente
XYZ
incluirse la línea en la salida o no?Respuestas:
Con
awk
usted puede hacer:Explicación: El primer
awk
argumento (out=file1
) define una variable con el nombre de archivo que se utilizará para la salida mientraslargefile
se procesa el argumento posterior ( ). Elawk
programa imprimirá todas las líneas en el archivo especificado por la variableout
({print >out}
). Si se encuentra el patrónXYZ
, la variable de salida se redefinirá para que apunte al nuevo archivo ({out="file2}"
) que se utilizará como destino para imprimir las líneas de datos posteriores.Referencias
fuente
Este es un trabajo para
csplit
:sería
s
ilently dividir el archivo, creando piezas con pref
IXfile
yn
umbered utilizando un solo dígito, por ejemplo,file0
etc Tenga en cuenta que el uso de/regex/
partiría hasta, pero sin incluir la línea que coincidenciasregex
. Para dividir e incluir la coincidencia de línea,regex
agregue un+1
desplazamiento:Esto crea dos archivos
file0
yfile1
. Si realmente necesita que se nombrenfile1
yfile2
siempre puede agregar un patrón vacío alcsplit
comando y eliminar el primer archivo:crea
file0
,file1
yfile2
aunquefile0
está vacío para que pueda quitar de forma segura:fuente
Con un moderno,
ksh
aquí hay una variante de shell (es decir, sinsed
) de una de lassed
respuestas basadas arriba:Y otra variante en
ksh
solo (es decir, también omitiendocat
):(La
ksh
solución pura parece ser bastante eficaz; en un archivo de prueba de 2.4 GB necesitaba 19-21 segundos, en comparación con 39-47 segundos con el enfoquesed
/cat
basado).fuente
read
yprint
, simplemente debe dejarlo ir a la salida por sí solo. El rendimiento mejora si construye el conjunto de herramientas AST por completo yksh
compila todos los componentes incorporados; es extraño para mí quesed
no sea uno de ellos, en realidad. Pero con cosas comowhile <file do
supongo que no es necesariosed
tanto ...awk
desempeñó en su punto de referencia? Y aunque estoy bastante seguro deksh
que siempre ganará esta pelea, si está utilizando un GNU con elsed
que no es muy justosed
:-u
nbuffered de GNU es un enfoque pobre para POSIXLY garantizar que el desplazamiento del descriptor se deja donde el programa se cerró - no debería ser necesario ralentizar el funcionamiento regular del programa - el almacenamiento en búfer está bien - todo lo quesed
debe hacer es buscar el descriptor cuando haya terminado. Por alguna razón, GNU revierte esa mentalidad.while
; la impresión se realiza implícitamente como el efecto secundario definido del<##
operador de redireccionamiento. Y solo se necesita imprimir la línea correspondiente. (De esa forma, la implementación de la función de shell es más flexible para admitir incl./excl.) Unwhile
ciclo explícito que esperaría que fuera significativamente más lento (pero no lo he verificado).head
lugar de laread
; parece que sólo un poco más lento, pero más concisa de código:{ head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3
.Con GNU
sed
deberías usar el-u
interruptor nbuffered. Sinsed
embargo, la mayoría de los otros s deberían funcionar.Para dejar a XYZ afuera ...
fuente
Prueba esto con GNU sed:
fuente
sed -e '1,/XYZ/{w file1' -e 'd}' large_file > file2
Un truco fácil es imprimir ya sea en STDOUT o STDERR, dependiendo de si el patrón de destino ha coincidido. Luego puede usar los operadores de redirección del shell para redirigir la salida en consecuencia. Por ejemplo, en Perl, suponiendo que se llama al archivo de entrada
f
y los dos archivos de salidaf1
yf2
:Descartando la línea que coincide con el patrón dividido:
Incluyendo la línea coincidente:
Alternativamente, imprima en diferentes identificadores de archivo:
Descartando la línea que coincide con el patrón dividido:
Incluyendo la línea coincidente:
fuente