Extraiga un valor de la salida del comando y use el valor como parámetro para un comando posterior

Extraiga un valor de la salida del comando y use el valor como parámetro para un comando posterior

Hola estoy tratando de tener

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

pase la salida al [TOKEN]campo aquí:

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

Sin embargo, no estoy familiarizado con JSON ya que mi resultado para el primer comando es

{
    "token": "value_of_token"
}

¿Cómo tomaría just "value_of_token"y conseguiría que así fuera [TOKEN]?

Respuesta1

Para tomar de manera más eficiente solo value_of_tokenla salida del curlcomando, canalice la salida a un solo sedcomando (editor de secuencias). Utilice la sustitución de comandos $()para almacenar la salida en una variable de shell:

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

Luego puede hacer referencia a la variable tokencomo parámetro del segundo curlcomando:

curl ... token="$token"

Explicación del sedcomando:

sed -n '/ *"token" *: *"/ { s///; s/".*//; p; q; }'
  • -nopción le dice sedanoimprimir cada línea de entrada

  • / *"token" *: *"/direcciona la línea que contiene el valor. Este patrón (expresión regular) coincide con todo el comienzo de la línea, hasta e incluyendo la primera comilla doble que delimita el valor del token.

  • {comience un bloque de comando que se aplicará a la línea direccionada.

  • s///;un comando sed para eliminar lo que coincidió anteriormente (en la parte de la dirección). La línea ("espacio de patrón") ahora se ve así:value_of_token"

  • s/".*//comando sed para eliminar las comillas dobles restantes ( ") y todo lo que sigue.

  • pcomando sed para imprimir la línea actual (editada) ("espacio de patrón" en sedterminología).

  • qSalga inmediatamente del script sed sin procesar más entradas

  • '}' finaliza el bloque de comando.

Por ejemplo,

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

Este método es mucho más eficiente que conectar otros 4 comandos para lograr el mismo resultado. Este sedcomando supone que no hay caracteres de tabulación en la entrada JSON. Si existen pestañas, el sedcomando requerirá modificación.

Respuesta2

Primero, tenga en cuenta que tuve que reemplazar la URL que tiene en sus comandos <URL>porque stackexchange pensó que estaba enviando spam y no me dejó publicar.

Bien, tienes dos preguntas aquí:

1) ¿Cómo se toma el resultado de un comando y se convierte en argumento de otro comando?

respuesta: El método más canónico sería utilizar la sustitución de comandos de Shell reemplazando su argumento en el segundo comando con $( <first command> )algo así:

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

Sin embargo, para facilitar la lectura, deberías hacer esto en líneas separadas guardando el resultado del primer comando y reutilizándolo así:

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

Además, para completar y porque preguntaste específicamente cómo "canalizar", puedes usar el comando xargs en lugar de la sustitución del comando de Shell:

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

Sin embargo, como notó, el resultado del primer comando no es exactamente lo que está buscando como token; por lo tanto, las soluciones anteriores no funcionarían como esperaba, lo que nos lleva a su siguiente pregunta:

2) ¿Cómo podemos aislar solo "valor_de_token" de toda la salida JSON?

Sin entrar en alguna API JSON, una simple canalización de grep, head y cut debería hacer el trabajo:

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"

Tenga en cuenta que esto head -1es solo en caso de que haya varias líneas de token en la salida, en cuyo caso solo se usa la primera.

Debes saber que esta no es una solución muy sólida si esta aplicación es importante. Si es así, realmente debería verificar el código de retorno y realizar una validación más exhaustiva de la salida del primer comando curl para no obtener resultados inesperados; pero eso requeriría un guión más amplio y está más allá del alcance de esta pregunta.

información relacionada