
Se puede hacer con otras herramientas, pero me interesa saber cómo puedo eliminar todas menos las últimas X líneas del archivo con sed
.
Respuesta1
Básicamente estás emulando la cola. X = 20 en este ejemplo. El siguiente ejemplo eliminará todas menos las últimas 20 líneas:
sed -i -e :a -e '$q;N;21,$D;ba' filename
Explicación:
- El -e :a crea una etiqueta llamada a
- La siguiente -e:
- $q - sale e imprime el espacio del patrón si es la última línea
- N - siguiente línea
- 21,$D: ejecuta el comando "D" si el número de línea es >= 21 (21,$ = línea 21 hasta $ que es el final del archivo)
- ba: ramas para etiquetar 'a', que es el comienzo del guión.
Respuesta2
sed
Es bastante complejo cuando se trata de una tarea como ésta. tail
, grep
o awk
haría esto mucho más fácil y debería usarse en su lugar. Dicho esto,esposible.
La siguiente solución está adaptada desed y búsqueda y reemplazo de varias líneas.
sed -ni '
# if the first line copy the pattern to the hold buffer
1h
# if not the first line then append the pattern to the hold buffer
1!H
# if the last line then ...
${
# copy from the hold to the pattern buffer
g
# delete current line if it is followed by at least X more lines
# replace X-1 with the proper value
s/.*\n\(\(.*\n\)\{X-1\}\)/\1/
# print
p
}
' filename
Sin los comentarios, es una frase ingeniosa. Si desea eliminar, por ejemplo, todo excepto las últimas diez líneas, utilice esto:
sed -ni '1h;1!H;${;g;s/.*\n\(\(.*\n\)\{9\}\)/\1/;p;}' filename
Respuesta3
Basado en el guión desección 4.13 del manual sedpodrías hacer algo como esto:
n=10
(( n > 1 )) && script='1h; 2,'$n'{H;g;}; $q; 1,'$((n-1))'d; N; D'
(( n > 1 )) || script='$!d'
sed -i "$script" infile
Respuesta4
tac|sed|tac>&&(mv||gato>)
Los siguientes fragmentos de comando eliminarán efectivamente todos excepto los mismos.último5líneasde ~/file1
. Si desea conservar elúltimo10líneas, puedes sustituir: |sed '1,5!d;'
por |sed '1,10!d;'
,etcétera, como veas conveniente.
tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&mv "/tmp/file2" ~/"file1"
tac ~/"file1" |sed '1,5!d;' |tac >"/tmp/file2" &&cat "/tmp/file2" >~/"file1"