2009-11-20 9 views
8

Ich sah ausWie sed verwenden, um etwas aus der ersten Zeile zurückzugeben, die übereinstimmt und früh aufgibt?

How to use sed to replace only the first occurrence in a file?

Wie die meisten tun, was ich will:

sed -n '0,/.*\(something\).*/s//\1/p' 

Dies findet das erste Spiel von etwas und extrahiert es (natürlich mein wirkliches Beispiel ist komplizierter) . Ich weiß, dass sed einen "quit" -Befehl hat, der es früh anhalten lässt, aber ich weiß nicht, wie man das "q" mit der obigen Zeile kombiniert, um mein gewünschtes Verhalten zu erhalten.

Ich habe versucht, das 'p' durch {p; q;} zu ersetzen, wie ich in einigen Beispielen gesehen habe, aber das funktioniert eindeutig nicht.

+0

Können Sie mehr zeigen, was Sie bekommen und was Sie wollen und wie sie sich unterscheiden? Ich habe 'echo -e 'aaa 111 aaa \ nbbb 111 bbb" | sed -n' 0, /. * \ (111 \). */S // \ 1/p'' und bekam eine "111". Dann habe ich 'echo -e 'aaa 111 aaa \ nbbb 111 bbb" | sed -n' 0,/\ (. * \ (111 \). * \)/S // \ 1/p'', um das zu zeigen volle Linie, um sicherzustellen, was es bekam und es "aaa 111 aaa" ausgab, was ich erwartet hatte. Beachten Sie, dass ich kein 'q' verwende. Wie funktioniert es nicht für dich? –

+0

Ihre Methode generiert zwar die korrekte Ausgabe, verarbeitet aber weiterhin die gesamte Datei, obwohl keine Arbeit mehr erforderlich ist, was für riesige Dateien oder die Verwendung in einer Pipeline schrecklich ist.Mein spezifischer Anwendungsfall war, über 'git log' auf einem git-p4 importierten Baum herauszufinden, welcher Verzweigungszweig für das letzte Commit verwendet wurde. git log (wenn ich ohne -n ​​angerufen werde, protokolliere jedes Commit, das passiert ist (Hunderttausende für mich). Wir können a priori nicht wissen, welchen Wert git für '-n' erhalten soll. Meine Lösung war: git log | sed -n '0, /. * \ [git-p4:. * \/\/depot \/blah \/\ ([^ \ /] * \) \ /.*/ s // \ 1/p;/\ [git-p4/q ' – nosatalian

Antwort

3

Mein spezifischen Anwendungsfall war auf einem git-p4 importierten Baum über ‚git log‘, um herauszufinden, welche Zweig notgedrungen verwendet wurde für die letzte begehen. git log (wenn ohne -n ​​aufgerufen wird, protokolliert jedes Commit, das passiert ist (Hunderttausende für mich)).

Wir können nicht a priori wissen, welchen Wert man für '-n' bekommt. Nachdem dieses Posting, fand ich meine Lösung, die war:

git log | sed -n '0,/.*\[git-p4:.*\/\/depot\/blah\/\([^\/]*\)\/.*/s//\1/p; /\[git-p4/ q' 

ich noch wissen möchte, wie dies zu tun, mit einem nicht ‚/‘ Separator und ohne den ‚git-p4‘ Teil zweimal angeben zu müssen einmal für die Extraktion und einmal für den Austritt. Es muss eine Möglichkeit geben, beide auf derselben Linie zu kombinieren ...

1

Sed hat normalerweise eine Option, um mehr als ein Muster zum Ausführen anzugeben (IIRC, es ist die -e Option). Auf diese Weise können Sie ein zweites Muster angeben, das nach der ersten Zeile beendet wird.

Ein anderer Ansatz besteht darin, sed zu verwenden, um die erste Zeile (sed '1q') zu extrahieren, dann zu einem zweiten sed Befehl (was Sie oben zeigen).

1

Verwendung gaffen

gawk '/MATCH/{ 
      print "do something with "$0 
      exit 
}' file 
9

Der Trick "Drucken und Beenden" funktioniert, wenn Sie auch den Substitutionsbefehl in den Block setzen (anstatt nur den Ausdruck zu setzen und dort zu beenden)).

Versuchen:

sed -n '/.*\(something\).*/{s//\1/p;q}' 

Lesen Sie diese wie: Spiel für das Muster zwischen den Schrägstrichen angegeben. Wenn dieses Muster gefunden wird, führen Sie die im Block angegebenen Aktionen aus: Ersetzen, Drucken und Beenden. In der Regel sind Match- und Substitutionsmuster gleich, aber dies ist nicht erforderlich, daher könnte der Befehl 's' auch einen anderen RE enthalten.

Eigentlich ist das ziemlich ähnlich zu dem, was ghostdog74 für gawk beantwortet.

+0

OpenBSD benötigt ein Semikolon nach dem Befehl quit ('q'). –

Verwandte Themen