Come usare sed per rimuovere le ultime n righe di un file

Voglio rimuovere alcune n righe dalla fine di un file. Questo può essere fatto usando sed?

Ad esempio, per rimuovere le righe da 2 a 4, posso usare

$ sed '2,4d' file 

Ma non conosco i numeri di linea. Posso cancellare l’ultima riga usando

 $sed $d file 

ma voglio sapere come rimuovere n righe dalla fine. Per favore fatemi sapere come farlo usando sed o qualche altro metodo.

Non so di sed , ma può essere fatto con la head :

 head -n -2 myfile.txt 

Dalle one-liner sed :

 # delete the last 10 lines of a file sed -e :a -e '$d;N;2,10ba' -e 'P;D' # method 1 sed -n -e :a -e '1,10!{P;N;D;};N;ba' # method 2 

Sembra essere quello che stai cercando.

Una soluzione sed & tac divertente e semplice:

 n=4 tac file.txt | sed "1,$n{d}" | tac 

NOTA

  • le doppie virgolette " sono necessarie per la shell per valutare la variabile $n nel comando sed . Nelle virgolette singole, non verrà eseguita alcuna interpolazione.
  • tac è un cat invertito, vedi man 1 tac
  • il {} in sed è lì per separare $n & d (se no, la shell tenta di interpolare la variabile $nd non esistente)

Se hardcoding n è un’opzione, è ansible utilizzare le chiamate sequenziali a sed. Ad esempio, per eliminare le ultime tre righe, elimina l’ultima riga tre volte:

 sed '$d' file | sed '$d' | sed '$d' 

Usa sed , ma lascia che la shell faccia i conti, con l’objective di usare il comando d dando un intervallo (per rimuovere le ultime 23 righe):

 sed -i "$(($(wc -l < file)-22)),\$d" file 

Per rimuovere le ultime 3 righe, dall'interno verso l'esterno:

 $(wc -l < file) 

Fornisce il numero di righe del file: ad esempio 2196

Vogliamo rimuovere le ultime 23 righe, quindi per lato sinistro o intervallo:

 $((2196-22)) 

Dà: 2174 Quindi l'interpretazione sed dopo shell è originale:

 sed -i 2174,$d file 

Con -i facendo modifica sul posto, il file è ora 2173 linee!

Potresti usare la testa per questo.

Uso

$ head --lines=-N file > new_file

dove N è il numero di linee che vuoi rimuovere dal file.

I contenuti del file originale meno le ultime N righe sono ora in new_file

Solo per completezza vorrei aggiungere la mia soluzione. Ho finito per farlo con lo standard ed :

 ed -s sometextfile <<< $'-2,$d\nwq' 

Questo elimina le ultime 2 righe usando la modifica sul posto (sebbene usi un file temporaneo in /tmp !!)

Questo potrebbe funzionare per te (GNU sed):

 sed ':a;$!N;1,4ba;P;$d;D' file 

Per troncare veramente file molto grandi abbiamo il comando truncate . Non conosce le linee, ma tail + wc può convertire le linee in byte:

 file=bigone.log lines=3 truncate -s -$(tail -$lines $file | wc -c) $file 

Esiste un’ovvia condizione di gara se il file viene scritto nello stesso momento. In questo caso potrebbe essere meglio usare head – conteggia i byte dall’inizio del file (IO del disco mentale), quindi tronceremo sempre il limite della linea (probabilmente più linee del previsto se il file è scritto triggersmente):

 truncate -s $(head -n -$lines $file | wc -c) $file 

Handy one-liner se non riesci ad accedere prova a inserire la password al posto del nome utente:

 truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure 

Con le risposte qui avresti già imparato che sed non è lo strumento migliore per questa applicazione.

Comunque penso che ci sia un modo per farlo usando sed; l’idea è di aggiungere N righe per contenere spazio fino a che non sei in grado di leggere senza colpire EOF. Quando viene colpito EOF, stampare il contenuto dello spazio di attesa e uscire.

 sed -e '$!{N;N;N;N;N;N;H;}' -ex 

Il comando sed sopra ometterà le ultime 5 righe.

La maggior parte delle risposte sopra sembrano richiedere comandi / estensioni GNU:

  $ head -n -2 myfile.txt -2: Badly formsd number 

Per una soluzione leggermente più portabile:

  perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;' 

O

  perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}' 

O

  awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }' 

Dove "10" è "n".

Prova il seguente comando:

 n = line number tail -r file_name | sed '1,nd' | tail -r 

Puoi ottenere il conteggio totale delle righe con wc -l e usarlo

head -n

Può essere fatto in 3 passaggi:

a) Contare il numero di righe nel file che si desidera modificare:

  n=`cat myfile |wc -l` 

b) Sottrai da quel numero il numero di righe da eliminare:

  x=$((n-3)) 

c) Indicare di cancellare dal numero di riga ( $x ) fino alla fine:

  sed "$x,\$d" myfile 

Preferisco questa soluzione;

 head -$(gcalctool -s $(cat file | wc -l)-N) file 

dove N è il numero di linee da rimuovere.

 sed -n ':pre 1,4 {N;b pre } :cycle $!{P;N;D;b cycle }' YourFile 

versione posix

Per eliminare le ultime 4 righe:

 $ nl -ba file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//' 

Sono arrivato con questo, dove n è il numero di linee che si desidera eliminare:

 count=`wc -l file` lines=`expr "$count" - n` head -n "$lines" file > temp.txt mv temp.txt file rm -f temp.txt 

È una piccola rotonda, ma penso che sia facile da seguire.

  1. Conta il numero di righe nel file principale
  2. Sottrarre il numero di linee che si desidera rimuovere dal conteggio
  3. Stampare il numero di righe che si desidera conservare e archiviare in un file temporaneo
  4. Sostituisci il file principale con il file temporaneo
  5. Rimuovi il file temporaneo

Questo rimuoverà le ultime 3 righe dal file :

for i in $(seq 1 3); do sed -i '$d' file; done;

Questo rimuoverà le ultime 12 righe

 sed -n -e :a -e '1,10!{P;N;D;};N;ba'