我正在尝试使用jq
:获取一些json数据
{
"meta": {
"title": "This is a title",
"description": "Just a description"
}
}
通过运行jq -r '.meta | .title, .description' ./project.json
,这给了我预期的结果:
This is a title
Just a description
现在我需要将内容分配给bash脚本中的一个变量:
read TITLE DESCRIPTION < <(echo $(jq -r '.meta | .title, .description' ./project.json))
但由于空间的原因,这是行不通的。后来我不得不逃离所有空间,我会用
echo ${TITLE// /\ }
我应该如何处理变量的赋值(处理空间内容(和转义空间(可能一步到位(?
不,您不需要逃离这里的任何内容。
使用NUL来分隔所有值,这样我们就可以正确地支持包含换行符的标题或描述:
{
IFS= read -r -d '' title
IFS= read -r -d '' description
} < <(jq -r '.meta | (.title, .description) | (., "u0000")' )
如果我们假设title
和description
不能包含文字换行符,则以下任一项都可以:
{
IFS= read -r title
IFS= read -r description
} < <(jq -r '.meta | .title, .description' ./project.json)
或者,告诉read
查找终止NUL,从而确保在jq
失败时它具有非零退出状态(但仍使用换行符分隔两个值(:
IFS=$'n' read -r -d '' title description < <(
jq -r '.meta | (.title, .description, "u0000")' ./project.json
)
利用jq对生成sh
兼容的eval安全转义的支持,我们还可以执行以下操作,可以正确处理带有换行符的字符串:
eval "$(jq -r '
.meta | "description=(.description|@sh); title=(.title|@sh)"
' ./project.json)"
内置mapfile
、bash
和数组(title(:
mapfile -t title < <(jq -r '.meta | .title, .description' project.json)
echo "${title[0]}"
echo "${title[1]}"
输出:
这是一个标题只是一个描述
使用一些参数替换:
$ x=$(jq ... )
$ title="${x%$'n'*}"
$ description="${x#*$'n'}"
$ typeset -p title description
declare -- title="This is a title"
declare -- description="Just a description"