Extraia um valor da saída do comando e use o valor como parâmetro para um comando subsequente

Extraia um valor da saída do comando e use o valor como parâmetro para um comando subsequente

Olá, estou tentando ter

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

passe a saída para o [TOKEN]campo aqui:

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

No entanto, não estou familiarizado com JSON, pois minha saída para o primeiro comando é

{
    "token": "value_of_token"
}

Como eu pegaria apenas "value_of_token"e faria com que fosse [TOKEN]?

Responder1

Para obter mais eficiência apenas value_of_tokenda saída do curlcomando, canalize a saída para um único sedcomando (editor de fluxo). Use a substituição de comando $()para armazenar a saída em uma variável shell:

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

Então você pode referenciar a variável tokencomo parâmetro para o segundo curlcomando:

curl ... token="$token"

Explicação do sedcomando:

sed -n '/ *"token" *: *"/ { s///; s/".*//; p; q; }'
  • -nopção diz sedparanãoimprimir cada linha de entrada

  • / *"token" *: *"/aborda a linha que contém o valor. Este padrão (expressão regular) corresponde a todo o início da linha, até e incluindo a primeira aspa dupla que delimita o valor do token.

  • {inicie um bloco de comando que será aplicado à linha endereçada.

  • s///;um comando sed para excluir o que foi correspondido anteriormente (na parte do endereço). A linha ("espaço padrão") agora se parece com:value_of_token"

  • s/".*//comando sed para excluir as aspas duplas restantes ( ") e tudo depois.

  • pcomando sed para imprimir a linha atual (editada) ("espaço padrão" na sedterminologia).

  • qSaia imediatamente do script sed sem processar mais nenhuma entrada

  • '}' finaliza o bloco de comando.

Por exemplo,

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

Este método é muito mais eficiente do que juntar 4 outros comandos para obter o mesmo resultado. Este sedcomando pressupõe que não há caracteres de tabulação na entrada JSON. Se existirem guias, o sedcomando exigirá modificação.

Responder2

Primeiro, observe que tive que substituir o URL que você tem em seus comandos <URL>porque o stackexchange pensou que eu estava enviando spam e não me deixou postar.

OK, você tem duas perguntas aqui:

1) Como você pega a saída de um comando e transforma-a em argumento de outro comando?

resposta: O método mais canônico seria usar a substituição de comando do shell, substituindo seu argumento no segundo comando por $( <first command> )algo assim:

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

No entanto, para fins de legibilidade, você realmente deve fazer isso em linhas separadas, salvando a saída do primeiro comando e reutilizando-a da seguinte forma:

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

Além disso, para completar e porque você perguntou especificamente como "canalizar", você poderia usar o comando xargs em vez da substituição de comando do shell:

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

No entanto, como você observou, a saída do primeiro comando não é exatamente o que você procura como token; portanto, as soluções acima não funcionariam como você espera, o que nos leva à sua próxima pergunta:

2) Como podemos isolar apenas “value_of_token” de toda a saída JSON?

Sem entrar em alguma API JSON, um simples pipeline de grep, head e cut deve resolver o problema:

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"

Observe que isso head -1ocorre apenas no caso de haver várias linhas de token na saída; nesse caso, apenas a primeira é usada.

Você deve saber que esta não é uma solução muito robusta se esta aplicação for importante. Se for, você realmente deve verificar o código de retorno e fazer uma validação mais extensa da saída do primeiro comando curl para não obter resultados inesperados; mas isso exigiria um script maior e está além do escopo desta questão.

informação relacionada