Tengo una gran cantidad de archivos, algunos de los cuales son muy largos. Me gustaría truncarlos a un cierto tamaño si son más grandes eliminando el final del archivo. Pero solo quiero eliminar líneas enteras. ¿Cómo puedo hacer esto? Se siente como el tipo de cosa que sería manejada por la cadena de herramientas de Linux, pero no sé cuál es el comando correcto.
Por ejemplo, supongamos que tengo un archivo de 120,000 bytes con líneas de 300 bytes y estoy tratando de truncarlo a 10,000 bytes. Las primeras 33 líneas deben permanecer (9900 bytes) y el resto debe cortarse. No quiero cortar exactamente a 10,000 bytes, ya que eso dejaría una línea parcial.
Por supuesto, los archivos tienen diferentes longitudes y las líneas no tienen la misma longitud.
Idealmente, los archivos resultantes se harían un poco más cortos en lugar de un poco más largos (si el punto de interrupción está en una línea larga), pero eso no es demasiado importante, podría ser un poco más largo si eso fuera más fácil. Me gustaría que los cambios se hicieran directamente a los archivos (bueno, posiblemente el nuevo archivo copiado en otro lugar, el original eliminado y el nuevo archivo movido, pero eso es lo mismo del POV del usuario). Una solución que redirige los datos a un montón de lugares y luego invita a la posibilidad de corromper el archivo y me gustaría evitar eso ...
fuente
Respuestas:
La complejidad
sed
/wc
se puede evitar en respuestas anteriores siawk
se usa. Usando el ejemplo proporcionado por OP (que muestra líneas completas antes de 10000 bytes):También muestra la línea completa que contiene el byte 10000 si ese byte no está al final de la línea:
La respuesta anterior supone:
\n
). Para archivos de texto Dos / Windows (\r\n
), cambielength() + 1
alength() + 2
LC_CTYPE=C
para forzar la interpretación en el nivel de byte.fuente
El
sed
enfoque está bien, pero no es posible recorrer todas las líneas. Si sabe cuántas líneas desea mantener (para tener un ejemplo, uso 99 aquí), puede hacerlo así:Explicación:
sed
es un procesador de expresiones regulares. Con la opción-i
dada, procesa un archivo directamente ("en línea"), en lugar de simplemente leerlo y escribir los resultados en la salida estándar.100,$
solo significa "desde la línea 100 hasta el final del archivo", y le sigue el comandod
, que probablemente adivinó correctamente para representar "eliminar". En resumen, el comando significa: "Eliminar todas las líneas desde la línea 100 hasta el final del archivo desde myfile.txt". 100 es la primera línea que se eliminará, ya que desea mantener 99 líneas.Editar: si, por otro lado, hay archivos de registro donde desea mantener, por ejemplo, las últimas 100 líneas:
Que esta pasando aqui:
[ $(wc -l myfile.txt) -gt 100 ]
: haga lo siguiente solo si el archivo tiene más de 100 líneas$((100 - $(wc -l myfile.txt|awk '{print $1}')))
: calcula el número de líneas para eliminar (es decir, todas las líneas del archivo excepto las (últimas) 100 para mantener)1, $((..)) d
: elimina todas las líneas de la primera a la línea calculadaEDITAR: como la pregunta se acaba de editar para dar más detalles, incluiré esta información adicional con mi respuesta también. Los hechos adicionales son:
A partir de estos datos, es posible calcular el número de líneas que quedan como "/", lo que con el ejemplo significaría 33 líneas. El término de shell para el cálculo:
$((size_to_remain / linesize))
(al menos en Linux usando Bash, el resultado es un entero). El comando ajustado ahora leería:Como los tamaños se conocen de antemano, ya no hay necesidad de un cálculo incrustado en el
sed
comando. Pero por flexibilidad, dentro de un script de shell uno puede usar variables.Para el procesamiento condicional basado en el tamaño del archivo, se puede usar la siguiente construcción de "prueba":
lo que significa: "si el tamaño de
$file
excede 100kB, haz ..." (ls -lk
enumera el tamaño del archivo en kB en la posición 5, porawk
lo tanto, se usa para extraer exactamente esto).fuente
head -n
.Al no encontrar un comando para hacer esto, escribí un script rápido (no probado):
fuente
Puede usar el comando linux sed para eliminar líneas de un archivo. El siguiente comando elimina la última línea de filename.txt:
Con awk o find puede buscar un patrón que coincida con su comando sed. Primero busca con awk o busca los archivos que deseas acortar y luego puedes eliminar las líneas con sed.
fuente
Hice algo similar con la cola. Para mantener solo las últimas 10,000 líneas en este caso:
fuente