将带空格的字符串分配给变量并转义这些空格



我正在尝试使用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")' )

如果我们假设titledescription不能包含文字换行符,则以下任一项都可以:

{
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)"

内置mapfilebash和数组(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"

最新更新