【问题标题】:Looping through variable with spaces用空格循环变量
【发布时间】:2020-11-28 06:18:21
【问题描述】:

这段代码按预期工作:

for var in a 'b c' d; 
do 
    echo $var; 
done

bash 脚本循环打印 3 个参数

a
b c
d

但是,如果这个字符串是通过 jq 读入的,然后像这样循环:

JSON_FILE=path/to/jsonfile.json
ARGUMENTS=$(jq -r '.arguments' "${JSON_FILE}")

for var in ${ARGUMENTS};
do 
    echo $var; 
done

结果是4个参数,如下:

a
'b
c'
d

供参考的示例json文件:

{
    "arguments" : "a 'b c' d"
}

这是什么原因?我尝试像其他 SO 答案中建议的那样在变量周围加上引号,但这导致所有内容都被视为 1 个参数。

我可以做些什么来获得第一种情况(3 个参数)的行为?

【问题讨论】:

  • 这能回答你的问题吗? Variable substitution in a for-loop using {$var}
  • 这与jq无关,严格来说是shell问题。
  • 您也许可以使用xargs 解析引用的字符串(请参阅我对超级用户问题"Get bash to respect quotes when word splitting subshell output" 的回答)(前提是字符串中的引用/转义匹配xargs' 语法) .这可能很难实现,具体取决于while 循环中的实际内容,但在最坏的情况下,您应该能够将其解析为 bash 数组,然后使用for var in "${arrayvar[@]}" 循环。
  • 如果您想使用 jq,请考虑将参数格式更改为数组,然后将数组内容输出到 while 循环。 stackoverflow.com/questions/33950596/…
  • Q 似乎有点混乱。拥有像 "a 'bc' d" 这样的 JSON 字符串似乎不太可能,但如果这是你真正拥有的,你要么必须根据你的要求在 jq 中解析它(它们是什么?),要么将它传递给一些外部程序解析。

标签: bash


【解决方案1】:

这是什么原因?

word splitting expansion 运行在其他扩展的未引用结果之上。因为for var in ${ARGUMENTS}; 中的${ARGUMENTS} 扩展没有被引用,所以会执行分词。不,分词会忽略变量扩展导致的引号 - 它只关心空格。

我可以做些什么来获得第一种情况(3 个参数)的行为?

好方法™是编写自己的解析器,解析字符串中的引号并根据引号拆分参数。

我建议使用xargs,它(默认情况下,通常是一种令人困惑的行为)解析输入字符串中的引号:

$ arguments="a 'b c' d"
$ echo "${arguments}" | xargs -n1 echo 
a
b c
d
# convert to array
$ readarray -t -d '' arr < <(<<<"${arguments}" xargs -n1 printf "%s\0")

如另一个答案中所述,您可以使用eval,但请不要使用eval is evil,它将在输入字符串上运行扩展。

【讨论】:

    猜你喜欢
    • 2012-10-23
    • 1970-01-01
    • 2014-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多