コマンド出力から値を抽出し、その値を後続のコマンドの引数として使用します。

コマンド出力から値を抽出し、その値を後続のコマンドの引数として使用します。

こんにちは欲しい

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

出力を[TOKEN]ここのフィールドに渡します。

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

しかし、最初のコマンドの出力は次のようになるため、JSONには慣れていません。

{
    "token": "value_of_token"
}

どうやってこれを受け入れて"value_of_token"実現できますか[TOKEN]

答え1

value_of_tokenコマンド出力の効率を最大化するには、curl出力を単一sed(ストリームエディタ)コマンドにパイプします。コマンド置換を使用して、$()出力をシェル変数に保存します。

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

tokenその後、その変数を2番目のコマンドのパラメータとして参照できますcurl

curl ... token="$token"

コマンドの説明sed:

sed -n '/ *"token" *: *"/ { s///; s/".*//; p; q; }'
  • -nオプションがsed教えてくれるいいえ各入力行を印刷します。

  • / *"token" *: *"/この値を含む行のアドレスを指定します。このパターン(正規表現)は、タグ値を区切る最初の二重引用符を含む行の最初の先頭に一致します。

  • {指定された行に適用されるコマンドブロックを開始します。

  • s///;sedコマンドは、以前に一致した内容(アドレス部分から)を削除します。これで、行(「パターンスペース」)は次のようになります。value_of_token"

  • s/".*//sedコマンドは、残りの二重引用符(")とそれの後のすべてのエントリを削除します。

  • psedコマンドは、現在(編集された)行(sed「パターンスペース」という用語)を印刷します。

  • qsed スクリプトをすぐに終了し、入力を処理しなくなりました。

  • '}' はコマンドブロックを終了します。

例えば、

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

この方法は、同じ結果を得るために4つの異なるコマンドをパイプするよりもはるかに効率的です。このsedコマンドは、JSON入力にタブ文字がないと仮定します。タブがある場合は、sedコマンドを変更する必要があります。

答え2

<URL>まず、stackexchangeは私がスパムを送信して投稿を許可しないと思ったので、コマンドでURLを置き換える必要がありました。

いいですね。ここに2つの質問があります。

1)あるコマンドの出力を取得し、それを別のコマンドの引数として使用する方法は?

A:最も標準化された方法は、シェルコマンドの置き換えを使用して2番目のコマンドのパラメータを次のように置き換えることです$( <first command> )

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

ただし、読みやすくするために、最初のコマンドの出力を次のように保存して再利用して、別の行でこれを行う必要があります。

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

また、完全性のために「パイプ」メソッドを具体的に要求したので、シェルのコマンド置換の代わりにxargsコマンドを使用できます。

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

ただし、指摘したように、最初のコマンドの出力は正確に必要なトークンではないため、上記の解決策は期待どおりに機能しないため、次の質問が発生します。

2)JSON出力全体から「value_of_token」をどのように分離しますか?

一部のJSON APIを使用せずに、単純なgrep、head、およびcutパイプラインで作業を実行できます。

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"

これはhead -1出力に複数のマーカーラインがある場合であり、この場合は最初のマーカーラインのみが使用されます。

このアプリケーションが重要な場合は、これはそれほど強力なソリューションではないことに注意してください。その場合は、最初のカールコマンドの戻りコードを確認し、出力に対してより広範な検証を実行して、予期しない結果が得られないようにする必要があります。ただし、これを行うにはより大きなスクリプトが必要であり、この質問の範囲外です。

関連情報