Habe nicht übereinstimmende Linien ignoriert


89

Wie kann ich sedFilter-Matching-Zeilen nach einem bestimmten Ausdruck erstellen, aber nicht übereinstimmende Zeilen ignorieren, anstatt sie drucken zu lassen?

Als echtes Beispiel möchte ich scalac(den Scala-Compiler) für eine Reihe von Dateien ausführen und -verbosedie .classerstellten Dateien aus der Ausgabe lesen . scalac -verbosegibt eine Reihe von Nachrichten aus, aber wir interessieren uns nur für die des Formulars [wrote some-class-name.class]. Was ich gerade mache, ist Folgendes ( |&ist Bash 4.0s Weg, um stderr zum nächsten Programm zu leiten):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/'

Dadurch werden die Dateinamen aus den Nachrichten extrahiert, an denen wir interessiert sind, aber auch alle anderen Nachrichten bleiben unverändert! Natürlich könnten wir stattdessen Folgendes tun:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
  sed 's/^\[wrote \(.*\.class\)\]$/\1/'

Das funktioniert, sieht aber sehr danach aus, das eigentliche Problem sedzu umgehen. So wird angewiesen , nicht übereinstimmende Zeilen von der Eingabe zu ignorieren. Wie machen wir das?


2
Die akzeptierte Antwort sollte die von mouviciel sein: stackoverflow.com/a/1665574/869951
Oliver

Antworten:


87

Ein anderer Weg mit einfachem Sed:

sed -e 's/.../.../;t;d'

s///ist eine Substitution, tohne Beschriftung überspringt bedingt alle folgenden Befehle, dlöscht Zeile.

Keine Notwendigkeit für Perl oder Grep.

(bearbeitet nach Nicholas Rileys Vorschlag)


3
Unter OS X 10.8.2 musste ich mich trennen txund dmit einem Zeilenumbruch anstatt mit einem Semikolon, wie ich es bekam undefined label 'x;d;:x'.
Davidchambers

6
Noch besser: sed -e 's/.../.../' -e 'tx' -e 'd' -e ':x'(vorgeschlagen in einem Kommentar zu einer ähnlichen Frage ).
Davidchambers

1
't' wird an das Ende des Skripts übertragen, wenn kein Etikett angegeben ist. Einfacher : sed -e 's/.../.../' -e 't' -e 'd'.
Nicholas Riley

Die Leute kennen die Bedeutung der -eOption nicht, also erwähnen Sie sie nicht allgemein.
Fredrick Gauss

238

Wenn Sie keine Zeilen drucken möchten, die nicht übereinstimmen, können Sie die Kombination von verwenden

  • -n Option, die sed anweist, nicht zu drucken
  • p Flag, das sed anweist, zu drucken, was übereinstimmt

Das gibt:

sed -n 's/.../.../p'

3
Ein Nachteil dieses Ansatzes ist, dass das Ergebnis auch mehrmals gedruckt wird, wenn mehrere Ausdrücke übereinstimmen. Beispiel: echo foo | sed -n -e 's/foo/bar/p' -e 's/bar/oof/p'Gibt beide barund oofin separaten Zeilen aus. Obwohl die goto-label-Variante auch nicht mehrere Muster verarbeiten kann, wird die Zeile gelöscht, wenn das erste Muster nicht übereinstimmt.
Rapsey

@ Rapsey, weil du sagst, es soll zweimal gedruckt werden. In dem einzelnen sed-Befehl, den Sie angewiesen haben, zweimal zu drucken, wird jede Instanz vor Ort gedruckt (oder möglicherweise gepuffert). Sie müssten entweder anstelle von -e pfeifen oder nur 'p' auf das letzte -e setzen.
mikrobielle

@ Rapsey: siehe meine Antwort zu diesem relevanten Punkt
Amessihel

@microbial, es funktioniert nicht, da das letzte p-Flag in jeder übereinstimmenden Zeile mit dem letzten Substitutionsausdruck funktioniert .
Amessihel

1

Verwenden Sie Perl:

... |& perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/'


0

Rapsey sprach einen relevanten Punkt über mehrere Substitutionsausdrücke an.

  • Erstens, eine Unix SE Antwort zitieren , können Sie „Präfix meisten sed Befehle mit einer Adresse , die Linien zu beschränken , auf die sie sich beziehen“.
  • Zweitens können Sie Befehle in geschweiften Klammern gruppieren {}(getrennt durch ein Semikolon ;oder eine neue Zeile).
  • Drittens fügen Sie das Druckflag p bei der letzten Ersetzung hinzu

Syntax:

sed -n -e '/^given_regexp/ {s/regexp1/replacement1/flags1;[...];s/regexp1/replacement1/flagsnp}'

Beispiel (siehe hier Dokument für weitere Details):

  • Code:

    sed -n -e '/^ha/ {s/h/k/gp;s/a/e/g}' <<SAMPLE
    haha
    hihi
    SAMPLE
    
  • Ergebnis:

    kaka
    
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.