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

3

Olá, estou tentando ter

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

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

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

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

{
    "token": "value_of_token"
}

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

    
por Micks Ketches 29.09.2016 / 23:54

2 respostas

2

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

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

Em seguida, você pode fazer referência à variável token como um parâmetro para o segundo comando curl :

curl ... token="$token"

Explicação do comando sed :

sed -n '/ *"token" *: *"/ { s///; s/".*//; p; q; }'
  • A opção -n informa sed a não imprime todas as linhas de entrada

  • / *"token" *: *"/ endereça a linha que contém o valor. Esse padrão (expressão regular) corresponde ao começo inteiro da linha, até e incluindo as primeiras aspas duplas que delimitam o valor do token.

  • { inicia um bloco de comando que será aplicado ao linha endereçada.

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

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

  • p sed comando para imprimir a linha atual (editada) ("espaço de padrão" na terminologia sed ).

  • q Saia imediatamente do script sed sem processar mais entradas

  • '}' termina 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 o encadeamento de outros 4 comandos para obter o mesmo resultado. Este comando sed assume que não há caracteres de tabulação na entrada JSON. Se as guias existirem, o comando sed exigirá modificações.

    
por 30.09.2016 / 05:34
0

Primeiro, por favor, note que eu tive que substituir o URL que você tem em seus comandos com <URL> porque o stackexchange achou que eu era spam e não me deixou postar.

OK, você tem duas perguntas aqui:

1) Como você tira a saída de um comando e faz dele um argumento de outro comando?

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

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ê 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 "pipe", 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, sua saída do primeiro comando não é exatamente o que você está procurando como seu token; Assim, 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 pipelining de grep, head e cut deve fazer o trabalho:

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"

Note que o head -1 é apenas para o caso de haver várias linhas de token da saída, caso em que apenas o primeiro é usado.

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

    
por 30.09.2016 / 02:19