Extrahieren Sie einen Wert aus der Befehlsausgabe und verwenden Sie den Wert als Parameter für einen nachfolgenden Befehl.

Extrahieren Sie einen Wert aus der Befehlsausgabe und verwenden Sie den Wert als Parameter für einen nachfolgenden Befehl.

Hallo, ich versuche,

curl -v --request POST https://example.com --data-urlencode "username=usr]” --data-urlencode "password=[pass]”

Übergeben Sie die Ausgabe [TOKEN]hier an das Feld:

curl -D - --request POST https://example.com --data-urlencode token=[TOKEN]

Ich bin jedoch mit JSON nicht vertraut, da meine Ausgabe für den ersten Befehl lautet

{
    "token": "value_of_token"
}

Wie kann ich es einfach angehen "value_of_token"und hinbekommen [TOKEN]?

Antwort1

Um möglichst effizient nur value_of_tokendie Ausgabe des curlBefehls zu übernehmen, leiten Sie die Ausgabe an einen einzelnen sed(Stream-Editor-)Befehl weiter. Verwenden Sie Befehlssubstitution, $()um die Ausgabe in einer Shell-Variable zu speichern:

token=$(curl ... | sed -n '/ *"token": *"/ { s///; s/".*//; p; }')

Anschließend können Sie die Variable tokenals Parameter für den zweiten curlBefehl referenzieren:

curl ... token="$token"

Erklärung des sedBefehls:

sed -n '/ *"token" *: *"/ { s///; s/".*//; p; q; }'
  • -nOption sagt sedzunichtjede Eingabezeile drucken

  • / *"token" *: *"/adressiert die Zeile, die den Wert enthält. Dieses Muster (regulärer Ausdruck) entspricht dem gesamten Zeilenanfang bis einschließlich des ersten Anführungszeichens, das den Token-Wert begrenzt.

  • {Beginnen Sie einen Befehlsblock, der auf die adressierte Zeile angewendet wird.

  • s///;ein sed-Befehl, um das zuvor passende zu löschen (im Adressteil). Die Zeile („Musterraum“) sieht nun so aus:value_of_token"

  • s/".*//sed-Befehl zum Löschen der verbleibenden doppelten Anführungszeichen ( ") und allem, was danach folgt.

  • psed-Befehl zum Drucken der aktuellen (bearbeiteten) Zeile (in der Terminologie „Musterraum“ sed).

  • qBeenden Sie das Sed-Skript sofort, ohne weitere Eingaben zu verarbeiten

  • '}' beendet den Befehlsblock.

Zum Beispiel,

$ echo '
{                          
    "token": "value_of_token"
}
' | sed -n '/ *"token" *: *"/ { s///; s/".*//; p; }'
value_of_token
$

Diese Methode ist viel effizienter als das Zusammenführen von 4 anderen Befehlen, um das gleiche Ergebnis zu erzielen. Dieser sedBefehl geht davon aus, dass die JSON-Eingabe keine Tabulatorzeichen enthält. Wenn Tabulatoren vorhanden sind, sedmuss der Befehl geändert werden.

Antwort2

Beachten Sie zunächst, dass ich die URL in Ihren Befehlen ersetzen musste, <URL>da Stackexchange der Meinung war, ich würde Spam versenden, und mir das Posten nicht gestattete.

OK, Sie haben hier zwei Fragen:

1) Wie machen Sie aus der Ausgabe eines Befehls ein Argument für einen anderen Befehl?

Antwort: Die gängigste Methode wäre, die Befehlsersetzung der Shell zu verwenden, indem Sie Ihr Argument im zweiten Befehl wie $( <first command> )folgt ersetzen:

curl -D - --request POST <URL> --data-urlencode token=$( curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” )

Aus Gründen der Lesbarkeit sollten Sie dies jedoch wirklich in separaten Zeilen tun, indem Sie die Ausgabe des ersten Befehls speichern und wie folgt wiederverwenden:

token=$( curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” )
curl -D - --request POST <URL> --data-urlencode token="$token"

Der Vollständigkeit halber und weil Sie speziell nach der Vorgehensweise beim „Pipe“ gefragt haben, könnten Sie anstelle der Befehlsersetzung der Shell auch den Befehl xargs verwenden:

curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” | xargs "curl -D - --request POST <URL> --data-urlencode token="{}

Wie Sie jedoch angemerkt haben, ist die Ausgabe Ihres ersten Befehls nicht ganz das, was Sie als Token suchen. Daher würden die oben genannten Lösungen nicht wie erwartet funktionieren, was uns zu Ihrer nächsten Frage bringt:

2) Wie können wir nur „value_of_token“ aus der gesamten JSON-Ausgabe isolieren?

Ohne auf die JSON-API eingehen zu müssen, sollte eine einfache Pipelining-Funktion von grep, head und cut genügen:

token=$( curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” ) | grep '"token":' | head -1 | cut -d ':' -f 2 | cut -d '"' -f 2
curl -D - --request POST <URL> --data-urlencode token="$token"

Beachten Sie, dass dies head -1nur für den Fall gilt, dass die Ausgabe mehrere Token-Zeilen enthält. In diesem Fall wird nur die erste verwendet.

Sie sollten wissen, dass dies keine sehr robuste Lösung ist, wenn diese Anwendung wichtig ist. Wenn dies der Fall ist, sollten Sie den Rückgabecode wirklich überprüfen und die Ausgabe des ersten Curl-Befehls umfassender validieren, damit Sie keine unerwarteten Ergebnisse erhalten. Dies würde jedoch ein größeres Skript erfordern und geht über den Rahmen dieser Frage hinaus.

verwandte Informationen