Voglio eliminare uno o più numeri di riga specifici da un file. Come lo farei usando sed?
Voglio eliminare uno o più numeri di riga specifici da un file. Come lo farei usando sed?
Risposte:
Se si desidera eliminare le righe da 5 a 10 e 12:
sed -e '5,10d;12d' file
Questo stamperà i risultati sullo schermo. Se si desidera salvare i risultati nello stesso file:
sed -i.bak -e '5,10d;12d' file
Questo eseguirà il backup del file file.bak
e cancellerà le righe indicate.
Nota: i numeri di riga iniziano da 1. La prima riga del file è 1, non 0.
sed -e '5,$d' file
sed -e '5d' file
. La sintassi è <address><command>
; dove <address>
può essere una linea singola 5
o un intervallo di linee come 5,10
, e il comando d
elimina la linea o le linee indicate. Gli indirizzi possono anche essere espressioni regolari o il simbolo del dollaro che $
indica l'ultima riga del file.
È possibile eliminare una determinata riga singola con il suo numero di riga da
sed -i '33d' file
Ciò eliminerà la riga sul numero di 33 righe e salverà il file aggiornato.
sed -i '0,/<TARGET>/{/<NEW_VALUE>/d;}' '<SOME_FILE_NAME>'
. Grazie!
e anche imbarazzato
awk 'NR!~/^(5|10|25)$/' file
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$
Questo è molto spesso un sintomo di un antipasto. Lo strumento che ha prodotto i numeri di riga può essere sostituito con uno che elimina immediatamente le righe. Per esempio;
grep -nh error logfile | cut -d: -f1 | deletelines logfile
(dov'è deletelines
l'utilità che stai immaginando di aver bisogno) è la stessa di
grep -v error logfile
Detto questo, se ti trovi in una situazione in cui hai davvero bisogno di eseguire questa attività, puoi generare un semplice sed
script dal file dei numeri di riga. Con umorismo (ma forse un po 'di confusione) puoi farlo sed
.
sed 's%$%d%' linenumbers
Questo accetta un file di numeri di riga, uno per riga, e produce, sullo standard output, gli stessi numeri di riga con l' d
aggiunta dopo ciascuno. Questo è uno sed
script valido , che possiamo salvare in un file o (su alcune piattaforme) reindirizzare a un'altra sed
istanza:
sed 's%$%d%' linenumbers | sed -f - logfile
Su alcune piattaforme, sed -f
non capisce l'argomento opzione -
per indicare l'input standard, quindi devi reindirizzare lo script su un file temporaneo e ripulirlo quando hai finito, o forse sostituire il trattino solitario con /dev/stdin
o /proc/$pid/fd/1
se il tuo sistema operativo (o shell ) ha questo.
Come sempre, è possibile aggiungere -i
prima -f
dell'opzione per sed
modificare il file di destinazione in luogo, invece di produrre il risultato sull'output standard. Su piattaforme * BSDish (incluso OSX) è necessario fornire anche un argomento esplicito -i
; un linguaggio comune è quello di fornire un argomento vuoto; -i ''
.
p
invece di d
, insieme all'opzione -n
(non funzionerà senza -n
e !d
non funzionerà neanche).
Vorrei proporre una generalizzazione con awk.
Quando il file viene creato da blocchi di dimensioni fisse e le righe da eliminare vengono ripetute per ciascun blocco, awk può funzionare bene in questo modo
awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print $0}'
OriginFile.dat > MyOutputCuttedFile.dat
In questo esempio la dimensione del blocco è 2000 e voglio stampare le linee [1..713] e [1026..1029].
NR
è la variabile utilizzata da awk per memorizzare il numero di riga corrente.%
fornisce il resto (o modulo) della divisione di due numeri interi;nl=((NR-1)%BLOCKSIZE)+1
Qui scriviamo nella variabile nl il numero di riga all'interno del blocco corrente. (vedi sotto)||
e &&
sono l'operatore logico OR e AND .print $0
scrive la riga completaWhy ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
+1 We add again 1 because we want to restore the desired order.
+-----+------+----------+------------+
| NR | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
| 1 | 1 | 0 | 1 |
| 2 | 2 | 1 | 2 |
| 3 | 0 | 2 | 3 |
| 4 | 1 | 0 | 1 |
+-----+------+----------+------------+