lineas - ¿Cómo puedo eliminar la primera línea de un archivo de texto usando el script bash/sed?
sed eliminar lineas (14)
¿Qué hay de usar csplit?
man csplit
csplit -k file 1 ''{1}''
Necesito eliminar repetidamente la primera línea de un gran archivo de texto usando un script de bash.
En este momento estoy usando sed -i -e "1d" $FILE
, pero toma alrededor de un minuto hacer la eliminación.
¿Hay una manera más eficiente de lograr esto?
¿Usar la cola en las líneas N-1 y dirigirlo a un archivo, luego eliminar el archivo anterior y cambiar el nombre del archivo nuevo al nombre anterior, hace el trabajo?
Si estuviera haciendo esto programáticamente, leería el archivo y recordaría el desplazamiento del archivo, después de leer cada línea, así que podría buscar esa posición para leer el archivo con una línea menos.
Como dijo Pax, probablemente no vas a llegar más rápido que esto. La razón es que casi no hay sistemas de archivos que admitan el truncado desde el principio del archivo, por lo que esta será una operación O ( n
) donde n
es el tamaño del archivo. Sin embargo, lo que puede hacer mucho más rápido es sobrescribir la primera línea con el mismo número de bytes (tal vez con espacios o un comentario) que podría funcionar para usted dependiendo de lo que está tratando de hacer exactamente (¿qué es eso por cierto?).
Debe mostrar las líneas excepto la primera línea:
cat textfile.txt | tail -n +2
La herramienta de sponge
evita la necesidad de hacer malabares con un archivo temporal:
tail -n +2 "$FILE" | sponge "$FILE"
No, eso es todo lo eficiente que vas a conseguir. Podría escribir un programa en C que podría hacer el trabajo un poco más rápido (menos tiempo de inicio y argumentos de procesamiento) pero probablemente tenderá a la misma velocidad que sed a medida que los archivos se vuelven grandes (y supongo que son grandes si se está demorando un minuto). ).
Pero su pregunta tiene el mismo problema que tantos otros, ya que presupone la solución. Si tuviera que decirnos en detalle lo que está tratando de hacer en lugar de cómo , podemos sugerirle una mejor opción.
Por ejemplo, si este es un archivo A que procesa algún otro programa B, una solución sería no quitar la primera línea, sino modificar el programa B para procesarlo de manera diferente.
Digamos que todos sus programas se agregan a este archivo A y el programa B actualmente lee y procesa la primera línea antes de borrarlo.
Puede volver a diseñar el programa B para que no intente eliminar la primera línea, pero mantiene un desplazamiento persistente (probablemente basado en el archivo) en el archivo A para que, la próxima vez que se ejecute, pueda buscar ese desplazamiento, proceso la línea allí, y actualizar el desplazamiento.
Luego, en un momento de silencio (¿medianoche?), Podría realizar un procesamiento especial del archivo A para eliminar todas las líneas procesadas actualmente y establecer el desplazamiento de nuevo en 0.
Sin duda, será más rápido para un programa abrir y buscar un archivo en lugar de abrir y reescribir. Esta discusión asume que usted tiene control sobre el programa B, por supuesto. No sé si ese es el caso, pero puede haber otras soluciones posibles si proporciona más información.
Para aquellos que están en SunOS que no es GNU, el siguiente código ayudará:
sed ''1d'' test.dat > tmp.dat
Podría usar vim para hacer esto:
vim -u NONE +''1d'' +''wq!'' /tmp/test.txt
Esto debería ser más rápido, ya que vim no leerá el archivo completo cuando se procesa.
Prueba la cola de GNU :
tail -n +2 "$FILE"
-nx
: Solo imprime las ultimas x
lineas. tail -n 5
le daría las últimas 5 líneas de la entrada. El tipo de signo +
invierte el argumento y hace que la tail
imprima todo menos las primeras líneas x-1
. tail -n +1
imprimirá todo el archivo, tail -n +2
todo menos la primera línea, etc.
La tail
GNU es mucho más rápida que la sed
. tail
también está disponible en BSD y la -n +2
es consistente en ambas herramientas. Consulte las páginas de manual de FreeBSD o OS X para obtener más información.
Sin embargo, la versión BSD puede ser mucho más lenta que sed
. Me pregunto cómo lograron eso; tail
debería leer un archivo línea por línea, mientras que sed
realiza operaciones bastante complejas que involucran la interpretación de un script, la aplicación de expresiones regulares y similares.
Nota: puede estar tentado a usar
# THIS WILL GIVE YOU AN EMPTY FILE!
tail -n +2 "$FILE" > "$FILE"
pero esto te dará un archivo vacío . La razón es que la redirección ( >
) ocurre antes de que el shell invoque a tail
:
- Shell trunca archivo
$FILE
- Shell crea un nuevo proceso para la
tail
- Shell redirige stdout del proceso de
tail
a$FILE
-
tail
lee desde el$FILE
ahora vacío
Si desea eliminar la primera línea dentro del archivo, debe usar:
tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
El &&
se asegurará de que el archivo no se sobrescriba cuando hay un problema.
Puede usar -i para actualizar el archivo sin usar el operador ''>''. El siguiente comando eliminará la primera línea del archivo y la guardará en el archivo.
sed -i ''1d'' filename
Puedes editar los archivos en el lugar: solo usa la marca -l de perl, así:
perl -ni -e ''print unless $. == 1'' filename.txt
Esto hace que la primera línea desaparezca, como pides. Perl necesitará leer y copiar el archivo completo, pero se encarga de que la salida se guarde con el nombre del archivo original.
Si desea modificar el archivo en su lugar, siempre puede usar la ed
original en lugar de su sucesor sucesor:
ed "$FILE" <<<$''1d/nwq/n''
Si lo que está buscando hacer es recuperarse después de una falla, simplemente podría crear un archivo que tenga lo que ha hecho hasta ahora.
if [[ -f $tmpf ]] ; then
rm -f $tmpf
fi
cat $srcf |
while read line ; do
# process line
echo "$line" >> $tmpf
done
Ya que parece que no puedo acelerar la eliminación, creo que un buen enfoque podría ser procesar el archivo en lotes como este:
While file1 not empty
file2 = head -n1000 file1
process file2
sed -i -e "1000d" file1
end
El inconveniente de esto es que si el programa muere en el medio (o si hay algún sql malo allí, lo que hace que la parte del "proceso" se muera o se bloquee), habrá líneas que se saltan o se procesan dos veces. .
(file1 contiene líneas de código sql)