Ich habe einen Befehl, der Daten an stdout ( command1 -p=aaa -v=bbb -i=4
) ausgibt . Die Ausgabezeile kann den folgenden Wert haben:
rate (10%) - name: value - 10Kbps
Ich möchte diese Ausgabe aufgreifen, um diese 'Rate' zu speichern (ich denke, Pipe wird hier nützlich sein). Und schließlich möchte ich, dass diese Rate ein Wert eines Parameters in einem zweiten Befehl ist (sagen wir mal command2 -t=${rate}
)
Es scheint auf meiner Seite knifflig zu sein; Ich würde gerne besser wissen, wie man Pfeifen, grep, sed und so weiter benutzt.
Ich habe viele Kombinationen wie diese ausprobiert, aber ich bin immer verwirrt von diesen:
$ command1 -p=aaa -v=bbb -i=4 | grep "rate" 2>&1 command2 -t="rate was "${rate}
So simulieren Sie die Ausgabe von
command1
Ich verwende diese Echo-Anweisung:Ein kurzer Test:
Das ist alles gut, also lasst es uns analysieren:
Damit wir die Linie bekommen, aus der wir wollen
command1
, lasst uns das weitergeben ancommand2
:Ich erwarte
"rate was "$(command1 | grep 'rate')
, automatisch zu verketten. Wenn dies aufgrund von Leerzeichen nicht funktioniert, sollten Sie in der Lage sein, die Eingabe stattdessen wie folgt zu übergeben:quelle
Versuchen Sie dies mit grep & pcre :
quelle
Die erste Aufgabe besteht darin, die Rate aus dieser Zeile zu extrahieren. Mit GNU grep (nicht eingebettetes Linux oder Cygwin) können Sie diese
-o
Option verwenden. Der gewünschte Teil enthält nur Ziffern, gefolgt von einem%
Zeichen. Wenn Sie das nicht%
selbst extrahieren möchten , benötigen Sie einen zusätzlichen Trick: eine Lookahead-Behauptung mit der Breite Null , die mit nichts übereinstimmt, aber nur dann, wenn diesem nichts folgt%
.Eine andere Möglichkeit ist die Verwendung von sed. Um einen Teil einer Zeile in sed zu extrahieren, verwenden Sie den
s
Befehl mit einer Regex, die mit der gesamten Zeile (beginnend mit^
und endend mit$
) übereinstimmt , und dem Teil, der in einer Gruppe (\(…\)
) beibehalten werden soll . Ersetzen Sie die gesamte Zeile durch den Inhalt der beizubehaltenden Gruppe (n). Übergeben Sie im Allgemeinen die-n
Option zum Deaktivieren des Standarddrucks und setzen Sie denp
Modifikator, um Zeilen zu drucken, in denen etwas zu extrahieren ist (hier gibt es eine einzelne Zeile, damit es keine Rolle spielt). Siehe Nur den Teil einer Linie nach einem übereinstimmenden Muster zurückgeben und einen mit 'sed' übereinstimmenden regulären Ausdruck extrahieren, ohne die umgebenden Zeichen zu drucken, um weitere sed-Tricks zu erhalten.Noch flexibler als sed, ist awk. Awk führt Anweisungen für jede Zeile in einer kleinen imperativen Sprache aus. Es gibt viele Möglichkeiten, den Kurs hier zu ermitteln. Ich wähle die zweiten Felder aus (Felder werden standardmäßig durch Leerzeichen begrenzt) und entferne alle Zeichen, die keine Ziffern sind.
Der nächste Schritt, nachdem Sie die Rate extrahiert haben, besteht darin, sie als Argument an zu übergeben
command2
. Das Werkzeug dafür ist eine Befehlssuspension . Wenn Sie einen Befehl eingeben$(…)
(in Dollar-Klammern), wird dessen Ausgabe in die Befehlszeile eingefügt. Die Ausgabe des Befehls wird in jedem Whitespace-Block in separate Wörter aufgeteilt, und jedes Wort wird als Platzhaltermuster behandelt. es sei denn , Sie dies geschehen soll, setzen Sie doppelte Anführungszeichen um den Befehl Substitution:"$(…)"
. Bei doppelten Anführungszeichen wird die Ausgabe des Befehls direkt als einzelner Parameter verwendet (die einzige Transformation besteht darin, dass Zeilenumbrüche am Ende der Ausgabe entfernt werden).quelle
Sie können
grep
PCRE - Perl - kompatible reguläre Ausdrücke verwenden. Auf diese Weise können Sie einen Lookbehind verwenden, der dem Wert von rate entspricht, ohne die Zeichenfolge "rate" in Ihre Ergebnisse aufzunehmen, wenn Sie danach suchen.Beispiel
Einzelheiten
Das oben
grep
Genannte funktioniert wie folgt:-o
Es wird nur das zurückgegeben, was wir suchen\d+
. Dies sind die Ziffern innerhalb der Parens.-P
Aktiviert die PCRE-Funktion von grep(?<=^rate \()
gibt nur Strings zurück, die mit "rate (" beginnenbefehl2
Um den Wert von "rate" zu ermitteln, können Sie folgendermaßen vorgehen
command1
:Dann würden Sie für Ihren 2. Befehl einfach diese Variable verwenden.
Sie könnten Lust bekommen und das alles zu einer einzigen Zeile machen:
Dadurch wird Befehl1 innerhalb des
$(..)
Ausführungsblocks ausgeführt, die Ergebnisse werden übernommen und in den-t=..
Schalter von Befehl2 aufgenommen .quelle
Normalerweise verwende ich `command`, um die Ausgabe als Argument für einen anderen Befehl zu platzieren. Um beispielsweise die von process foo auf freebsd verbrauchte Ressource zu finden, gilt Folgendes:
Hier wird pgrep verwendet, um die PID des Prozesses foo zu extrahieren, die an den Befehl procstat übergeben wird, der die PID des Prozesses als Argument erwartet.
quelle