Löschen bestimmte Zeilennummer (n) aus einer Textdatei sed Verwendung?
-
22-09-2019 - |
Frage
Ich mag aus einer Datei einer oder mehr bestimmten Zeilennummern löschen. Wie würde ich dies unter Verwendung von sed tun?
Lösung
Wenn Sie Zeilen löschen 5 bis 10 und 12:
sed -e '5,10d;12d' file
Damit werden die Ergebnisse auf dem Bildschirm drucken. Wenn Sie die Ergebnisse auf die gleiche Datei speichern:
sed -i.bak -e '5,10d;12d' file
Dadurch wird die Datei bis zu file.bak
zurück, und löschen Sie die gegebenen Linien.
. Hinweis: Die Zeilennummern beginnen bei 1. Die erste Zeile der Datei 1, nicht 0
Andere Tipps
Sie können eine bestimmte einzelne Zeile mit Zeilennummer löschen, indem Sie sed -i '33d' Datei
Dies wird die Linie auf 33 Zeilennummer löschen und die aktualisierte Datei speichern.
und awk als auch
awk 'NR!~/^(5|10|25)$/' file
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$
Dies ist sehr oft ein Symptom für eine Antipattern. Das Werkzeug, das die Zeilennummern erzeugt wird, kann auch mit einer ersetzt werden, die direkt den Zeilen löschen. Zum Beispiel:
grep -nh error logfile | cut -d: -f1 | deletelines logfile
(wobei deletelines
ist das Dienstprogramm Sie stellen sich vor, Sie brauchen) ist die gleiche wie
grep -v error logfile
sagte, hat, wenn Sie in einer Situation sind, wo Sie wirklich diese Aufgabe ausführen müssen, können Sie einen einfachen sed
Skript aus der Datei der Zeilennummern erzeugen können. Humoristisch (aber vielleicht etwas verwirrend) Sie können dies tun, mit sed
.
sed 's%$%d%' linenumbers
Dies eine Datei von Zeilennummern akzeptiert, einem pro Zeile, und erzeugt auf der Standardausgabe, die gleichen Zeilennummern mit d
nach jedem angehängt. Dies ist eine gültige sed
Skript, das wir in eine Datei speichern können, oder (auf einigen Plattformen) Rohr an einem anderen sed
Beispiel:
sed 's%$%d%' linenumbers | sed -f - logfile
Auf einigen Plattformen sed -f
versteht nicht die Option Argument -
Standardeingabe zu verstehen, so dass Sie das Skript in eine temporäre Datei zu umleiten haben, und reinigen Sie es, wenn Sie fertig sind, oder vielleicht den einsamen Strich mit /dev/stdin
ersetzen oder /proc/$pid/fd/1
wenn Ihr Betriebssystem (oder Schale) hat den.
Wie immer können Sie -i
vor der -f
Option hinzufügen sed
bearbeiten die Zieldatei an seinem Platz zu haben, anstatt das Ergebnis auf der Standardausgabe zu erzeugen. An * BSDish Plattformen (einschließlich OSX) benötigen Sie ein explizites Argument -i
zu liefern als auch, eine gemeinsame Idiom ist ein leeres Argument zu liefern; -i ''
.
Ich möchte eine Verallgemeinerung mit awk vorzuschlagen.
Wenn die Datei durch die Blöcke einer festen Größe gemacht wird und die Linien zu löschen sind für jeden Block wiederholt, awk kann fein in einer solchen Art und Weise arbeiten
awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print $0}'
OriginFile.dat > MyOutputCuttedFile.dat
In diesem Beispiel wird die Größe für den Block 2000, und ich mag die Linien drucken [1..713] und [1026..1029].
-
NR
ist die Variable von awk verwendet, um die aktuelle Zeilennummer zu speichern. -
%
gibt den Rest (oder Modul) der Division zweier ganzer Zahlen; -
nl=((NR-1)%BLOCKSIZE)+1
Hier schreiben wir in der Variablen nl die Zeilennummer innerhalb des aktuellen Blocks. (Siehe unten) -
||
und&&
ist der logische Operator ODER und und . -
print $0
schreibt die durchgezogene Linie
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 |
+-----+------+----------+------------+