En ¿Cómo puedo usar el entorno? variables en el cuerpo de una solicitud PUT de curl?, se me dio el gran consejo de siempre usar " usando variables de entorno.

Di que quiero hacer la siguiente consulta:

curl -XPUT http://"${HOST}"/create/"${USER}" -d'{"user":"'"${USER}"'"}'

Incluí ${USER} entre " para asegurar que los espacios en el nombre de usuario sean posibles. Hice lo mismo para ${HOST}, aunque eso no era estrictamente necesario, ya que los nombres de host no pueden contener espacios hasta donde yo sé.

Me pregunto si la siguiente solicitud es igual a la solicitud anterior:

curl -XPUT "http://${HOST}/create/${USER}" -d'{"user":"'"${USER}"'"}'

Son iguales? ¿Cuál es el preferido / el más estándar?

1
bitwisedeprevation 19 feb. 2018 a las 18:17

2 respuestas

La mejor respuesta

Sí, ellas son iguales.

Preferiría

curl -XPUT "http://${HOST}/create/${USER}" -d"{\"user\":\"${USER}\"}"

Primero porque:

  1. es más corto como dijo @Ryan en el comentario
  2. El segundo literal es más legible cuando está en un fragmento en lugar de concatenar dos estilos de comillas.
  3. algunos editores los resaltarán de manera más legible (por ejemplo, vim por ejemplo, vim)
1
tworec 20 feb. 2018 a las 11:41

Como ha visto, lidiar con las convenciones de citas en Bash cuando tiene datos arbitrarios es difícil. Sin embargo, hay una tercera forma de citar en casos como este que puede hacer la vida mucho más fácil: " aquí documentos ".

El uso de <<TOKEN en un comando de shell indica que las líneas después del comando se leerán como la entrada estándar del comando, terminadas con TOKEN . Dentro del documento aquí, los caracteres habituales entre comillas pierden su significado especial y se interpretan literalmente, pero la sustitución de variables todavía ocurre normalmente.

Para demostrarlo, inicie un netcat "servidor" para mostrar las solicitudes en una terminal con

nc -kl localhost 8888

Ahora, en otra terminal, ejecute este script de shell:

name="Alice's Restaurant"
password="quote is ' and doublequote is \\\"."
curl -XPUT http://localhost:8888/create/user --data-binary @- <<EOF
{
  "name": "$name",
  "password": "$password",
  "created": "$(date --iso-8601)"
}
EOF

Cuando se proporciona un argumento --data @ que solicita que curl lea los datos del nombre de archivo especificado inmediatamente después de @, y use - como el nombre del archivo lee de stdin.

Tenga en cuenta que aquí utilizo --data-binary para hacer que la salida del servidor sea más fácil de entender; en el uso de producción, querría usar --data-urlencode o, si el servidor acepta datos en otro formato, asegúrese de configurar el encabezado Content-type en ese formato en lugar de dejarlo en el {{X3 }}.

Cuando ejecute lo anterior, verá lo siguiente en su terminal netcat:

PUT /create/user HTTP/1.1
Host: localhost:8888
User-Agent: curl/7.52.1
Accept: */*
Content-Length: 112
Content-Type: application/x-www-form-urlencoded

{
  "name": "Alice's Restaurant",
  "password": "quote is ' and doublequote is \".",
  "created": "2018-02-20"
}

Como puede ver, los caracteres de comillas normales no se tratan de manera especial, no necesita hacer ninguna cita especial en las variables de shell individuales que se expanden dentro del documento aquí, e incluso puede usar $() para ejecutar comandos de shell cuya salida será sustituido dentro del documento.

(Por cierto, especifiqué la comilla doble dentro de la variable de contraseña como \\\", configurándola en \" en la variable después de la interpolación de shell de una cadena entre comillas dobles, porque eso es necesario para producir JSON válido. Oh, nunca puedes escapar de los problemas de cotización).

0
cjs 20 feb. 2018 a las 15:01