"Unexpected $end" 使用 bash 变量时

"Unexpected $end" when using bash variables

我有一个相当简单的 bash 脚本,我想根据环境变量的值启用或禁用 jq 过滤器。

这是脚本的简化版本:

JSON='{ "key1": { "name":"foo" }, "key2": { "name":"bar" } }'
OPTIONAL_FILTER=""
if [[ "$FLAG" == "value" ]]; then
    OPTIONAL_FILTER='| select(.key == "key2")'
fi
jq 'to_entries[] '${OPTIONAL_FILTER}' | .value.name' <<< $JSON

当我 运行 使用 FLAG="" 的脚本时,一切都按预期工作,我得到输出:

"foo"
"bar"

但是如果我设置FLAG="value",然后我得到以下错误:

jq: error: syntax error, unexpected $end (Unix shell quoting issues?) at <top-level>, line 1:
to_entries[] |
jq: 1 compile error

当我 运行 在 zsh 中执行相同的命令时,我没有收到此错误,我得到的只是 "foo"

的预期输出

我在 shell 脚本方面不是很有经验。我猜我的字符串中插入了一个空字符或其他类似的输入终止符,但我无法确认这一点或找到一个好的替代方法。它特别令人烦恼,因为它似乎是 shell-特定的。我用于大部分测试的 zsh 可以很好地处理代码。当我尝试 运行 一个我看到错误的 .sh 脚本时,我只会收到该错误。

最终目标是使可选过滤器正常工作。如果我错过了一个特定于 jq 的选项,我愿意接受其他选择。我尝试使用 jq 'to_entries[] $ENV.OPTIONAL_FILTER | .value.name' <<< $JSON,但得到 jq: error: syntax error, unexpected '$', expecting $end

> bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)

您插入 ${OPTIONAL_FILTER} 的方式导致它被分成多个单词,这意味着 jq 收到的参数比预期的多。 Bash 解释命令就像你写的一样:

jq 'to_entries[] |' 'select(.key' '==' '"key2")' '| .value.name' <<< $JSON

您可以引用它以确保它是一个单词:

jq 'to_entries[] '"${OPTIONAL_FILTER}"' | .value.name' <<< $JSON

或者在整个过程中使用双引号,这样您就不必跳入跳出单引号:

jq "to_entries[] ${OPTIONAL_FILTER} | .value.name" <<< $JSON

有关详细信息,请参阅:

如果可能,几乎总是最好避免通过字符串插值来操纵程序文本;幸运的是,据我所知,使用 jq 不仅可行而且非常简单。

在当前情况下,您可以使用 --arg command-line 选项,如下所示:

jq --arg flag "$FLAG" '
  to_entries[]
  | if $flag == "value" then select(.key == "key2")
    else . end
  | .value.name' <<< $JSON