Bash脚本中jq遍历JSON无法输出含空格完整字符串的问题
问题原因与解决方法
原因
Bash默认以空格、制表符、换行作为字段分隔符(IFS)。当你用jq 'to_entries[]'输出key=value格式的字符串时,若value包含空格,Bash会将空格后的内容视为独立的命令参数,导致赋值时仅读取到第一个空格前的部分。而直接指定字段读取时,通常会通过引号包裹输出或正确处理赋值逻辑,因此能获取完整内容。
解决方法
假设你的service-data.json内容如下:
{ "name": "my-service", "description": "This is a test service with spaces" }
方法1:用while循环+read命令避免分词
通过进程替换逐行读取jq输出,同时设置IFS=防止read截断空格,-r保留原始字符,确保变量在当前shell生效:
while IFS= read -r line; do export "$line" done < <(jq -r 'to_entries[] | "\(.key)=\(.value)"' service-data.json) # 验证:输出完整内容 echo "$description"
IFS=会临时清空字段分隔符,保证read把整行内容作为一个整体处理;进程替换< <()避免管道创建子shell,让赋值的变量能在当前脚本环境中使用。
方法2:用jq的@sh过滤器自动适配Shell语法
jq的@sh过滤器会将字符串转换为符合Shell语法的格式,自动为含特殊字符(空格、引号等)的内容添加引号,再通过eval执行赋值:
eval "$(jq -r 'to_entries[] | "export \(.key)=\(.value|@sh)"' service-data.json)" # 验证 echo "$description"
这种方式更安全,能处理除空格外的其他特殊字符(如单引号、换行),省去手动处理引号的麻烦。
错误写法示例(对比参考)
以下写法会导致字段截断,请勿使用:
# 错误:直接用for循环遍历,Bash会按空格分词 for entry in $(jq -r 'to_entries[] | "\(.key)=\(.value)"' service-data.json); do export "$entry" done # 此时echo $description仅输出"This"
内容的提问来源于stack exchange,提问作者Basit
相关产品推荐
相关产品推荐

