Analizar una cadena en el script bash

Revisé otras respuestas pero no pude obtener una explicación adecuada de cómo hacer esto.

Yo tener una variable de cadena llamada id tal que id="{"name":"john"}". ¿Cómo puedo obtener 2 variables de esta cadena como-

key="name" value="john" 

Se agradecería una explicación detallada ya que quiero comprender el análisis de cadenas en bash.

Hasta ahora, «he eliminado las llaves {} de la cadena-

id="$( echo "${id}" | tr -d {} )" 

No puedo» incluir " allí como arroja un error. También busca algo como id.split(":") al final para obtener una matriz.

Comentarios

  • ¿Podemos advertirle de esta táctica / pista antes de que ‘ sea demasiado tarde? Parece que tiene json o algún otro dato estructurado allí; tal vez una herramienta dedicada sería una forma más segura de llegar a donde está ¿vas a ir?
  • Vi que jq es usado por otros, pero no hay forma de que pueda analizar esto sin un tercero herramienta?
  • ¿Está incorporando estos datos desde un archivo? ¿Podría haber más de un par de clave / valores? ¿Cómo se vería una comilla doble como parte del valor?
  • @kev: Técnicamente awk, sed y grep también son herramientas de terceros. Si está utilizando json datos, no hay absolutamente ninguna razón para no tener las herramientas adecuadas para trabajar con ellos.
  • Estos datos son el resultado de un comando que ejecutado en mi script. Siempre estará en este formato: 1 clave y 1 valor.

Respuesta

Usando jq:

id="{"name":"john"}" key=$(jq -r keys[] <<<"$id") value=$(jq -r .[] <<<"$id") 

-r: con esta opción, si el filtro «s el resultado es una cadena, entonces se escribirá directamente en la salida estándar en lugar de formatearse como una cadena JSON con comillas.

keys: las teclas de función integradas, cuando dado un objeto, devuelve sus claves en una matriz.


Usando json:

id="{"name":"john"}" key=$(json -ak <<<"$id") value=$(json -a "$key" <<<"$id") 

-a procesa la entrada como una matriz

-k devuelve valores clave

Comentarios

  • gracias por la explicación. Funciona muy bien. Creo que ‘ s no hay forma de analizar una cadena sin jq en scripts bash.
  • @kev: Hay muchas formas de analizar cadenas, pero es ‘ un poco injusto para llamar a esto una cadena y no datos json.
  • @kev Los datos JSON se pueden codificar. Para analizarlo, potencialmente tendría que decodificarlo. Además, JSON no se preocupa por los espacios en blanco (líneas nuevas, etc.) entre claves y valores, por lo que debería tenerlo en cuenta. Esto ya lo han hecho los autores del analizador JSON subyacente en jq.

Respuesta

Literalmente pediste understand string parsing in bash, así que escribiré una respuesta con eso en mente, aunque sea el solución incorrecta para su problema . Puedes usar bash para hacer lo que quieras, si tienes realmente limpio datos sin caracteres especiales, donde especial se define como cualquier cosa fuera de [A-Za-z0-9 ]:

$name":"john"}" $ # remove everything through the first "{" $ echo $id "name":"john"} $ # remove everything starting with the last "}" $ echo $id "name":"john" $ name="${id%:*}" # take everything before the ":" $ name="${name//\"/}" # remove quotes $ echo $name name $ value="${id#*:}" # take everything after the ":" $ value="${value//\"/}" # remove quotes $ echo $value john 

Todo esto se describe en «Expansión de parámetros» en el manual de bash . Por ejemplo, ${parameter#word} que Remove matching prefix pattern eliminará el texto word del comienzo de $parameter. De manera similar, % elimina el sufijo. // reemplaza todas las apariciones de una cadena con lo que venga después (en el ${foo//\"/} ejemplo anterior, las comillas (que deben escaparse) aparecen como \") se reemplazan con la cadena vacía). Sin embargo, debe realizar cada sustitución por sí sola: no puede eliminar el principio y de la cadena con un comando.

Probablemente también haya notado que necesita escapar de caracteres especiales, como }, { y ". Siempre que recuerde hacerlo bien, puede escribir código como este con bastante facilidad, pero, por simple que sea, tiende a ser código de solo escritura. Cuando vuelva a esto código en un año o dos para reutilizarlo, «mirarás algo como #*\{} y pensarás, WTF, ¿eso siquiera significa? y luego simplemente cópielo a ciegas en un nuevo proyecto y luego su código se romperá de una manera sutil porque encuentra caracteres especiales que no esperaba.

Los ejemplos anteriores se romperán si los pares de nombre-valor tienen caracteres especiales, como llaves, comillas o dos puntos de escape o probablemente otros caracteres. Así que esto funcionará bien para un raspado rápido y sucio o para el caso de uso del 80%, pero realmente no debería usarlo en producción o en cualquier momento que necesite asegurarse de que siempre funcione con cualquier entrada.

Incluso sin las echo declaraciones allí para mostrarle lo que está sucediendo, puede ver que este código ya es más largo que los ejemplos en la otra respuesta que muestran cómo hacerlo adecuadamente. Entonces, al no usar una herramienta de terceros, se está dando más código para escribir, lo que le llevará más tiempo escribir y depurar, y también terminará con una solución que es menos flexible y que romperse cuando encuentra algo inesperado.

Comentarios

  • esto fue bastante informativo – can ‘ t comprender por qué la gente votaría en contra

Responder

Alternativamente, podría usar un Unix basado en walk-path utilidad jtc :

id="{"name":"john"}" bash $ key=$(jtc -w"[0]<>k" <<<"$id") bash $ echo $key "name" bash $ value=$(jtc -w"[0]" <<<"$id") bash $ echo $value "john" bash $ 

PS> Divulgación: Soy el creador de la jtc – herramienta shell cli para operaciones JSON

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *