Ich möchte zwei bestimmte aufeinanderfolgende Zeilen löschen, die mit Mustern aus einer bestimmten Zeile einer Datei übereinstimmen.
Der Dateiinhalt sieht beispielsweise wie folgt aus:
Line1: a
Line2: b
Line3: c
Line4: Name: 123
Line5: xyz
Line6: Name: 456
Line7: abc
Ich möchte die Zeilen ab Zeile 4 suchen, die dem Muster der ersten Zeile entsprechen, das mit „Name:“ beginnt, und die dem Muster der zweiten Zeile entsprechen, das mit einem Leerzeichen beginnt, und die beiden aufeinanderfolgenden Zeilen löschen.
sed
Gibt es eine effiziente Möglichkeit, dies mithilfe der Shell oder auf andere Weise zu tun ?
Um es etwas deutlicher zu machen: Ich möchte Signatur-/Prüfsummeninformationen aus MANIFEST.MF entfernen.
Beispiel für MANIFEST.MF wie unten: Aus der unten stehenden Manifestdatei möchte ich den Eintrag „Name: “ entfernen. Dabei kann der Eintrag „Name: “ eine oder zwei (oder mehr) Zeilen umfassen.
Meine Lösung bestand zunächst darin, den ersten Eintrag „Name:“ zu suchen, gefolgt vom Eintrag „SHA-256-Digest:“, und dann bis zum Ende der Datei zu löschen. Leider besteht bei dieser Lösung das Problem, dass ein benötigter Eintrag in der Mitte entfernt wird. Beispielsweise wird „NetBeans-Simply-Convertible:“ ebenfalls entfernt.
Ich möchte jetzt den Eintrag „Name:“ entfernen, wenn er in einer Zeile vorhanden ist oder sich über zwei oder mehr Zeilen erstreckt. Beim Entfernen von „Name:“-Einträgen sollten jedoch keine Einträge wie „NetBeans-Simply-Convertible:“ verloren gehen.
Ich entferne bereits "SHA-256-Digest: "-Einträge mit dem folgenden Befehl aus der Datei mitsed -i "/^\SHA-256-Digest: /d" $manifest_file
Manifest-Version: 1.0
Version-Info: ....
Name: com/abc/xyz/pqr/client/relationship/message/notifier/Relati
onshipUpdateNotifierFactory.class
SHA-256-Digest: cSSyk6Y2L2F9N6FPtswUkxjF2kelMkGe4bFprcQ+3uY=
Name: com/abc/xyz/pqr/client/relationship/ui/BaseRelationshipView
$5.class
SHA-256-Digest: w9HgRjDuP024U4CyxeKPYFe6rzuzxZF3b+9LVG36XP8=
Name: com/abc/xyz/pqr/client/impl/MofRelationshipAgentImpl.class
SHA-256-Digest: GwIBIU+UdPtjyRhayAVM90Eo+SwCT/kP65dI59adEnM=
Name: com/abc/xyz/pqr/client/settings/ConvertibleProperties.class
NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
vertibleProperties
SHA-256-Digest: 5FszAtfpPXcLx/6FBWbfeg6E4fwFMRozV+Q+3rReATc= ...
Erwartete Ausgabe:
Manifest-Version: 1.0
Version-Info: ....
NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
vertibleProperties
...
Antwort1
awkAnsatz:
Nehmen wir an, wir haben die folgende Eingabedatei file.txt
(wobei jede Zeile Line<number>:
als erstes Feld enthält):
Line1: a
Line2: b
Line3: c
Line4: Name: 123
Line5: xyz
Line6: Name: 456
Line7: abc
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11: abc
Line12: Name: 333
Line13: ccc
awk '{ if ($2 == "Name:") {
if ((getline l) > 0){
if (l ~ /^\S+ \S+/) { next } else { print $0 RS l }
}
} else { print }
}' file.txt
Die Ausgabe:
Line1: a
Line2: b
Line3: c
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11: abc
'getline var'- liest den nächsten Datensatz aus der awk-Eingabe in die Variablevar
DergetlineDer Befehl gibt 1 zurück, wenn ein Datensatz gefunden wird, und 0, wenn das Dateiende erreicht ist.
Antwort2
Sie sehen, dass Ihre Frage nicht klar ist: Eine Antwort löscht 4 Zeilen (die beiden übereinstimmenden und die beiden nachfolgenden); eine andere löscht allesAberdie passenden Zeilen...
Ich werfe ein, was ich verstehe, was Sie wollen: Ich lösche 2 Zeilen, die übereinstimmende Name: 123
und die folgende. Ich mache das mit sed
:
sed -e '/Name: 123/{N;d}' filename
Antwort3
Verwendung von ed
:
$ printf '%s\n' 'g/^ / s///\' '-,.j' 'g/^Name: /d' 'g/SHA-256-Digest: /d' '4,$g/^$/d' ,p Q | ed -s file
Manifest-Version: 1.0
Version-Info: ....
NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}ConvertibleProperties
Dadurch wird das folgende Bearbeitungsskript auf Ihre Eingabedatei angewendet:
g/^ / s///\
-,.j
g/^Name: /d
g/SHA-256-Digest: /d
4,$g/^$/d
,p
Q
Dieses besteht aus sechs einzelnen Befehlen:
Die beiden Befehle
s///
werden-,. j
auf jede Zeile angewendet, die mit einem Leerzeichen beginnt. Der leere reguläre Ausdruck ims
Befehl verwendet den Ausdruck^
des vorhergehendeng
Befehls erneut (der zum Anwenden eines oder mehrerer Befehle auf Zeilen verwendet wird, die einem regulären Ausdruck entsprechen), sodass ders
Befehl das erste Leerzeichen in Zeilen entfernt, die mit Leerzeichen beginnen. Derj
Befehl verbindet dann die geänderte Zeile mit der vorherigen Zeile. Dadurch wird der Zeilenumbruch in den Eingabedaten effektiv rückgängig gemacht.Der Befehl
d
wird auf alle Zeilen angewendet, die mit beginnenName:
, und entfernt diese.Ebenso
SHA-256-Digest:
werden Zeilen entfernt, die mit beginnen.Ab Zeile 4 werden leere Zeilen entfernt.
Um das Ergebnis anzuzeigen, geben wir den kompletten Puffer auf die Standardausgabe aus.
Q
beendet den Editor bedingungslos (Sie könnten verwenden,wq
um die Änderungen in die Originaldatei zurückzuschreiben).
Antwort4
sed -e '
4,$!d; # skip non-relevant portion
/Name:/N; # grab the line coming after Name:
/\n.* /d; # what we were after is not this
P;D
' yourfile