web-dev-qa-db-ja.com

コマンド出力から値を抽出し、その値を後続のコマンドのパラメーターとして使用します

こんにちは私は持っていることを試みています

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]にするにはどうすればよいですか?

3
Micks Ketches

curlコマンドの出力から_value_of_token_だけを最も効率的に取得するには、出力を単一のsed(ストリームエディター)コマンドにパイプします。コマンド置換$()を使用して、出力をシェル変数に格納します。

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

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

_curl ... token="$token"
_

sedコマンドの説明:

_sed -n '/ *"token" *: *"/ { s///; s/".*//; p; q; }'
_
  • _-n_オプションは、sednotすべての入力行を出力するように指示します

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

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

  • _s///;_以前に一致したもの(住所部分)を削除するsedコマンド。行(「パターンスペース」)は次のようになります:_value_of_token"_

  • _s/".*//_ sedコマンドを使用して、残りの二重引用符(_"_)とそれ以降のすべてを削除します。

  • p sedコマンドは、現在の(編集された)行(sed用語の「パターンスペース」)を出力します。

  • q入力を処理せずに、sedスクリプトをすぐに終了します

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

例えば、

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

この方法は、同じ結果を達成するために他の4つのコマンドを一緒にパイプするよりもはるかに効率的です。このsedコマンドは、JSON入力にタブ文字がないことを前提としています。タブが存在する場合、sedコマンドを変更する必要があります。

3
RobertL

まず、stackexchangeがスパムだと思って投稿させてくれなかったため、コマンドにあるURLを_<URL>_に置き換える必要があることに注意してください。

ここで、2つの質問があります。

1)あるコマンドの出力をどのようにして別のコマンドの引数にするのですか?

回答:最も標準的な方法は、次のように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_は、出力から複数のトークン行が発生した場合に備えています。

このアプリケーションが重要な場合、これはそれほど堅牢なソリューションではないことを知っておく必要があります。そうである場合は、の戻りコードを実際に確認し、最初のcurlコマンドからの出力をより広範囲に検証して、予期しない結果が発生しないようにする必要があります。しかし、それはより大きなスクリプトを必要とし、この質問の範囲を超えています。

0
Kyndig