it-swarm.com.de

Bestimmte Zeilennummern mit sed? Aus einer Textdatei löschen

Ich möchte eine oder mehrere bestimmte Zeilennummern aus einer Datei löschen. Wie würde ich das mit sed machen?

211
Justin Ethier

Wenn Sie die Zeilen 5 bis 10 und 12 löschen möchten:

sed -e '5,10d;12d' file

Dadurch werden die Ergebnisse auf dem Bildschirm gedruckt. Wenn Sie die Ergebnisse in derselben Datei speichern möchten:

sed -i.bak -e '5,10d;12d' file

Dies sichert die Datei bis zu file.bak und lösche die angegebenen Zeilen.

Hinweis: Zeilennummern beginnen bei 1. Die erste Zeile der Datei ist 1, nicht 0.

336
Brian Campbell

Sie können eine bestimmte einzelne Zeile mit ihrer Zeilennummer mit sed -i '33d' file löschen

Dadurch wird die Zeile mit der Zeilennummer 33 gelöscht und die aktualisierte Datei gespeichert.

40
amit

und awk auch

awk 'NR!~/^(5|10|25)$/' file
25
ghostdog74
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$ 
16

Dies ist sehr oft ein Symptom für ein Antimuster. Das Werkzeug, das die Zeilennummern erzeugt hat, kann durchaus durch ein Werkzeug ersetzt werden, das die Zeilen sofort löscht. Zum Beispiel;

grep -nh error logfile | cut -d: -f1 | deletelines logfile

(wobei deletelines das Dienstprogramm ist, von dem Sie sich vorstellen, dass Sie es benötigen) ist dasselbe wie

grep -v error logfile

Wenn Sie sich jedoch in einer Situation befinden, in der Sie diese Aufgabe wirklich ausführen müssen, können Sie aus der Datei mit Zeilennummern ein einfaches sed -Skript generieren. Humorvoll (aber vielleicht etwas verwirrend) können Sie dies mit sed tun.

sed 's%$%d%' linenumbers

Dies akzeptiert eine Datei mit Zeilennummern, eine pro Zeile, und erzeugt bei der Standardausgabe dieselben Zeilennummern, nach denen jeweils d angehängt wird. Dies ist ein gültiges sed Skript, das wir in einer Datei speichern oder (auf einigen Plattformen) auf eine andere sed Instanz umleiten können:

sed 's%$%d%' linenumbers | sed -f - logfile

Auf einigen Plattformen versteht sed -f Das Optionsargument - Nicht als Standardeingabe. Sie müssen das Skript daher in eine temporäre Datei umleiten und anschließend bereinigen Ersetzen Sie den Bindestrich durch /dev/stdin oder /proc/$pid/fd/1, wenn dies in Ihrem Betriebssystem (oder in Ihrer Shell) der Fall ist.

Wie immer können Sie -i Vor der Option -f Hinzufügen, damit sed die Zieldatei bearbeitet, anstatt das Ergebnis in der Standardausgabe zu erzeugen. Auf * BSDish-Plattformen (einschließlich OSX) müssen Sie auch ein explizites Argument für -i Angeben. eine übliche Redewendung ist, ein leeres Argument zu liefern; -i ''.

6
tripleee

Ich möchte eine Verallgemeinerung mit awk vorschlagen.

Wenn die Datei aus Blöcken fester Größe besteht und die zu löschenden Zeilen für jeden Block wiederholt werden, funktioniert awk auf diese Weise einwandfrei

awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print  $0}'
 OriginFile.dat > MyOutputCuttedFile.dat

In diesem Beispiel beträgt die Blockgröße 2000 und ich möchte die Zeilen [1..713] und [1026..1029] drucken.

  • NR ist die Variable, mit der awk die aktuelle Zeilennummer speichert.
  • % Gibt den Rest (oder den Modul) der Division von zwei ganzen Zahlen an;
  • nl=((NR-1)%BLOCKSIZE)+1 Hier schreiben wir in die Variable nl die Zeilennummer innerhalb des aktuellen Blocks. (siehe unten)
  • || Und && Sind die logischen Operatoren [~ # ~] oder [~ # ~] und [~ # ~] und [~ # ~] .
  • print $0 Schreibt die ganze Zeile

Why ((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      |
+-----+------+----------+------------+

2
Hastur