I'm trying to get some json data using jq
:
{
"meta": {
"title": "This is a title",
"description": "Just a description"
}
}
by running jq -r '.meta | .title, .description' ./project.json
, which gives me the expected result:
This is a title
Just a description
Now I need to assign the content to a variable in my bash script:
read TITLE DESCRIPTION < <(echo $(jq -r '.meta | .title, .description' ./project.json))
But this is not working because of the spaces. Also later I have to escape all spaces, which I would do with:
echo ${TITLE// /\\ }
How should I handle the assignment of the variable (handling space content) and escape the spaces (maybe in one step)?
CodePudding user response:
No, you don't need to escape anything here.
Using NULs to delimit all values, so we can correctly support titles or descriptions that contain newlines:
{
IFS= read -r -d '' title
IFS= read -r -d '' description
} < <(jq -r '.meta | (.title, .description) | (., "\u0000")' )
If we assume that title
and description
cannot contain literal newlines, either of the below will do:
{
IFS= read -r title
IFS= read -r description
} < <(jq -r '.meta | .title, .description' ./project.json)
...or, telling read
to look for a terminating NUL, and thereby ensuring that it has a nonzero exit status should jq
fail (but still using a newline to separate the two values):
IFS=$'\n' read -r -d '' title description < <(
jq -r '.meta | (.title, .description, "\u0000")' ./project.json
)
Taking advantage of jq's support for generating sh
-compatible eval-safe escaping, we can also do the following, which does correctly handle strings with newlines:
eval "$(jq -r '
.meta | "description=\(.description|@sh); title=\(.title|@sh)"
' ./project.json)"
CodePudding user response:
With builtin mapfile
, bash
and an array (title):
mapfile -t title < <(jq -r '.meta | .title, .description' project.json)
echo "${title[0]}"
echo "${title[1]}"
Output:
This is a title Just a description
CodePudding user response:
Using some parameter substitutions:
$ x=$(jq ... )
$ title="${x%$'\n'*}"
$ description="${x#*$'\n'}"
$ typeset -p title description
declare -- title="This is a title"
declare -- description="Just a description"