Wie lösche ich alles nach dem zweiten Auftreten von Anführungszeichen über die Befehlszeile?

7

Ich habe diesen Speicher in einer Variablen

   sCellEventTrap-03-28 TRAP-TYPE - CAC-Code: 00
        ENTERPRISE compaq
        VARIABLEN {scellNameDateTime,
                     scellSWComponent,
                     scellECode,
                     scellCAC,
                     scellEIP}
        BESCHREIBUNG
             "Schweregrad: Normal - informativer Natur. Bei einem physischen Laufwerk ist während einer regelmäßigen Laufwerksprüfung eine Inkonsistenz des ID-Blocks aufgetreten."
           - # TYP "StorageCell-Ereignis"
           - # ZUSAMMENFASSUNG "SCellName-TimeDate% s: SWCID% d: ECode:% d: CAC% d: EIP% d."
           - # ARGUMENTE {0,1,2,3,4,}
           - # SEVERITY INFORMATIONAL
           - # TIMEINDEX 136
           - # STAATLICHE WARNUNG
        :: = 13600808

Ich soll alles bis zum zweiten Auftreten von schneiden ". Das würde mir also geben:

 sCellEventTrap-03-28 TRAP-TYPE - CAC-Code: 00
        ENTERPRISE compaq
        VARIABLEN {scellNameDateTime,
                     scellSWComponent,
                     scellECode,
                     scellCAC,
                     scellEIP}
        BESCHREIBUNG
             "Schweregrad: Normal - informativer Natur. Bei einem physischen Laufwerk ist während einer regelmäßigen Laufwerksprüfung eine Inkonsistenz des ID-Blocks aufgetreten."

Ein anderes Beispiel

    genericSanEvent TRAP-TYPE
        ENTERPRISE hpSanManager
        VARIABLEN {Schweregrad, Kategorie, ID,
                     msgString, contactName, contactEmail,
                     contactWorkPhone, contactHomePhone, 
                     contactPager, contactFax}
        BESCHREIBUNG
                        "Ein generisches SAN-Ereignis ist aufgetreten. Die Variablen sind:
                            Schweregrad - der Schweregrad des Ereignisses;
                            Kategorie - Kategorie des gemeldeten Ereignisses;
                            Code - ID des Ereignisses in der angegebenen Kategorie;
                            msgString - die beschreibende Nachrichtenzeichenfolge
                                das Ereignis;
                            contactName - der Name der Person
                                über das Ereignis informiert werden;
                            contactEmail - die E-Mail-Adresse des
                                Person, auf die in contactName verwiesen wird;
                            contactWorkPhone - die geschäftliche Telefonnummer
                                der Person, auf die in Bezug genommen wird 
                                Kontaktname;
                            contactHomePhone - die private Telefonnummer
                                der Person, auf die in Bezug genommen wird 
                                Kontaktname;
                            contactPager - die Pager-Nummer des 
                                Person, auf die in contactName verwiesen wird;
                            contactFax - die Faxnummer der Person
                                 in contactName bezeichnet "
     - Die folgenden Attribute werden von xnmloadmib zur verbesserten Formatierung verwendet
     - # TYP "OV SAM SAN-Ereignis"
     - # ZUSAMMENFASSUNG "OV SAM SAN-Ereignis, Kategorie / ID:% d /% d, Nachricht:% d Schweregrad:% d Kontakt:% d"
     - # ARGUMENTE {1,2,3,0,4}
     - # SEVERITY CRITICAL
     - # GENERIC 6
     - # KATEGORIE "Application Alert Events"
     - # SOURCE_ID "T"
        :: = 1

Die Ausgabe für dieses Beispiel sollte sein:

    genericSanEvent TRAP-TYPE
        ENTERPRISE hpSanManager
        VARIABLEN {Schweregrad, Kategorie, ID,
                     msgString, contactName, contactEmail,
                     contactWorkPhone, contactHomePhone, 
                     contactPager, contactFax}
        BESCHREIBUNG
                        "Ein generisches SAN-Ereignis ist aufgetreten. Die Variablen sind:
                            Schweregrad - der Schweregrad des Ereignisses;
                            Kategorie - Kategorie des gemeldeten Ereignisses;
                            Code - ID des Ereignisses in der angegebenen Kategorie;
                            msgString - die beschreibende Nachrichtenzeichenfolge
                                das Ereignis;
                            contactName - der Name der Person
                                über das Ereignis informiert werden;
                            contactEmail - die E-Mail-Adresse des
                                Person, auf die in contactName verwiesen wird;
                            contactWorkPhone - die geschäftliche Telefonnummer
                                der Person, auf die in Bezug genommen wird 
                                Kontaktname;
                            contactHomePhone - die private Telefonnummer
                                der Person, auf die in Bezug genommen wird 
                                Kontaktname;
                            contactPager - die Pager-Nummer des 
                                Person, auf die in contactName verwiesen wird;
                            contactFax - die Faxnummer der Person
                                 in contactName bezeichnet "

SamFlynn
quelle
@ John1024 Ich habe es versucht, sed 's/"[^"]*$//'aber es löscht nur das " und nichts danach. So bleibt das Ganze nur ein "wird gelöscht.
SamFlynn
@ John1024 hat dies auch versucht, awk -F ""\" '{print $1 (NF>1? FS $2 : "")}' temp1 aber das gleiche wie oben passiert.
SamFlynn

Antworten:

9

Mit awk:

awk -v RS='"' -v ORS='"' 'NR==1{print} NR==2{print; printf"\n";exit}' file

Dies setzt das Datensatztrennzeichen auf ". Wir wollen also die ersten beiden Datensätze drucken und dann sind wir fertig. Ausführlicher:

  • -v RS='"'

    Dadurch wird das Trennzeichen für Eingabedatensätze auf ein doppeltes Anführungszeichen gesetzt.

  • -v ORS='"'

    Dies setzt das Trennzeichen für den Datensatz auf ein doppeltes Anführungszeichen.

  • NR==1{print}

    Dies weist awk an, die erste Zeile zu drucken.

  • NR==2{print; printf"\n";exit}

    Dies weist awk an, die zweite Zeile zu drucken, dann ein Zeilenumbruchzeichen zu drucken und dann zu beenden.

Mit sed

sed -r 'H;1h;$!d;x; s/(([^"]*"){2}).*/\1/' file

Dadurch wird die gesamte Datei auf einmal eingelesen. Wenn die Datei also sehr groß ist, verwenden Sie diesen Ansatz nicht. Es funktioniert wie folgt:

  • H;1h;$!d;x

    Dies ist eine nützliche Sed-Redewendung: Sie liest die gesamte Datei auf einmal ein.

  • s/(([^"]*"){2}).*/\1/

    Dies sucht nach dem zweiten "und löscht dann den gesamten Text, der auf das zweite Zitat folgt.

    Der reguläre Ausdruck (([^"]*"){2})erfasst den gesamten Text bis einschließlich des zweiten doppelten Anführungszeichens und speichert ihn in Gruppe 1. Der reguläre Ausdruck .*erfasst alles, was bis zum Ende der Datei folgt. Der Ersatztext ist Gruppe 1 , \1.

John1024
quelle
Hier habe ich versucht, eine sed-Zeile zu schreiben, aber ich habe nur die gefunden, sed -e '0,/"/! {$!N;d;}' temp1die bei seiner ersten funktioniert hat, aber bei der zweiten kläglich versagt. Gute Arbeit bei Ihrer Antwort. Es deckt definitiv beides ab! +1
Terrance
Vorschlag: Versuchen Sie NR <3. Das sollte den Code verkürzen.
Sergiy Kolodyazhnyy
3

Verwenden von Perl:

< infile perl -0777 -pe 's/((.*?"){2}).*/$1/s' > outfile
  • -0777: schlürft die gesamte Datei auf einmal anstatt jeweils einer Zeile
  • -p: Platziert eine while (<>) {[...]}Schleife um das Skript und druckt die verarbeitete Datei
  • -e: liest das Skript aus den Argumenten

Aufschlüsselung der Perl-Befehle:

  • s: behauptet, eine Substitution durchzuführen
  • /: Startet das Muster
  • ((.*?"){2}): Stimmt eine beliebige Anzahl von Zeichen innerhalb der aktuellen Datei null oder mehrmals träge ab und gruppiert sie (dh sie stimmt so wenig wie möglich überein und stoppt, wenn das folgende Muster zu stimmen beginnt) vor einem "Zeichen zweimal
  • .*: Entspricht einer beliebigen Anzahl von Zeichen, die null oder mehrmals gierig in der aktuellen Datei enthalten sind (dh sie stimmen so oft wie möglich überein).
  • /: stoppt das Muster / startet die Ersatzzeichenfolge
  • $1: wird durch die erste erfasste Gruppe ersetzt
  • /: stoppt die Ersatzzeichenfolge / startet die Modifikatoren
  • s: behandelt die gesamte Datei als einzelne Zeile, sodass .auch Zeilenumbrüche übereinstimmen
kos
quelle
3

Obwohl viele Programme keine sehr langen Zeilen als Eingabe mögen, können Sie bei nicht großen Datenmengen häufig den mehrzeiligen Abgleich vereinfachen, indem Sie zuerst die Daten bearbeiten, um alles in eine Zeile zu setzen, den Abgleich durchführen und dann die neuen Zeilen wiederherstellen.

Verwenden Sie beispielsweise tr, um die neue Zeile \ndurch ein Zeichen zu ersetzen, das nicht in Ihren Daten enthalten ist (ich habe Wagenrücklauf `\ r 'verwendet), verwenden Sie sed, um diese einzelne Zeile zu ändern, und tr das Zeichen zurück:

tr '\n' '\r' < file |
sed 's/\("[^"]*"\).*/\1/' |
( tr '\r' '\n';  echo ) # add a final newline

Andernfalls verwenden Sprachen wie Perl und Python ähnliche reguläre Ausdrücke wie diese und eignen sich gut zum Bearbeiten mehrzeiliger Zeichenfolgen, obwohl Sie angeben, dass Sie sed / awk / grep möchten. ZB Perl:

perl -e '$_ = join("",<>); s/(".*?").*/$1/s; print "$_\n"; ' file
meuh
quelle
3

Hier ist ein kleines pythonSkript:

#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
    print '"'.join(f.read().split('"')[:2]) + '"'
  • f.read().split('"')liest die gesamte Datei als Zeichenfolge und teilt sie dann auf ", um alle "getrennten Teile zu erhalten

  • Da wir nur an den ersten beiden "getrennten Teilen interessiert sind , '"'.join(f.read().split('"')[:2])werden die ersten beiden mit verbunden"

  • Dann haben wir endlich ein hinzugefügt ", um das gewünschte Format zu erhalten.

heemayl
quelle
2

Hier ist eine kürzere awkVersion:awk '/TRAP-TYPE/,/[[:alpha:]]*"$/ '

$ awk '/TRAP-TYPE/,/[[:alpha:]]*"$/ ' testfile.txt                             
   sCellEventTrap-03-28 TRAP-TYPE  -- CAC Code: 00
        ENTERPRISE compaq
        VARIABLES  { scellNameDateTime,
                     scellSWComponent,
                     scellECode,
                     scellCAC,
                     scellEIP}
        DESCRIPTION
             "Severity: Normal -- informational in nature. A physical disk drive has experienced an ID block inconsistency during a periodic drive check."


$ awk '/TRAP-TYPE/,/[[:alpha:]]*"$/ ' testfile2.txt                                                 
    genericSanEvent TRAP-TYPE
        ENTERPRISE hpSanManager
        VARIABLES  { severityLevel, category, id,
                     msgString, contactName, contactEmail,
                     contactWorkPhone, contactHomePhone, 
                     contactPager, contactFax }
        DESCRIPTION
                        "A generic SAN event has occurred.  The variables are:
                            severityLevel - the event severity level;
                            category - Category of the event being reported;
                            code - ID of the event in the given category;
                            msgString - the message string describing
                                the event;
                            contactName - the name of the individual
                                to be notified of the event;
                            contactEmail - the e-mail address of the
                                individual referred to in contactName;
                            contactWorkPhone - the work phone number
                                of the individual referred to in 
                                contactName;
                            contactHomePhone - the home phone number
                                of the individual referred to in 
                                contactName;
                            contactPager - the pager number of the 
                                individual referred to in contactName;
                            contactFax - the FAX number of the individual
                                 referred to in contactName"
Sergiy Kolodyazhnyy
quelle