使用bash变量时出现“意外的$ end”

问题描述

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

这是脚本的简化版本:

       i     lat     lon                 name   country continent elevation type        value Rep.$ Rep.D Rep.G Rep.H Rep.P Rep.S Rep.T  Rep.V Rep.W Rep.Dp Rep.Pt
0   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2019-12-31Z  1380    SW    34  79.5  1019    25   7.9  13000     8    4.6      F
1   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z     0    SW    32  84.0  1018    21   7.5  13000     8    5.0      F
2   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z    60    SW    34  81.7  1018    22   7.5  12000     8    4.6      F
3   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   120    SW    36  79.9  1017    24   7.9  11000     8    4.7      F
4   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   180    SW    40  82.3  1016    23   7.5  13000     8    4.7      F
5   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   240    SW    33  84.6  1015    18   8.0  12000     8    5.6      F
6   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   300    SW    33  85.3  1015    24   8.3  11000     8    6.0      F
7   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   360   WSW    41  89.0  1014    30   8.5   8000     8    6.8      F
8   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   420    SW    43  89.6  1013    28   8.7   7000     7    7.1      F
9   3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   480    SW    39  88.4  1013    23   8.7  15000     7    6.9      F
10  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   540    SW    40  84.3  1013    29   9.1  19000     8    6.6      F
11  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   600    SW    41  85.4  1012    24   8.9  12000     8    6.6      F
12  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   660    SW    38  84.2  1012    28   9.2  13000     8    6.7      F
13  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   720    SW    47  83.6  1011    32   9.4  12000     8    6.8      F
14  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   780   WSW    45  84.8  1011    30   9.4  11000     8    7.0      F
15  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   840    SW    43  86.0  1010    28   9.4  11000     7    7.2      F
16  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   900   WSW    40  85.4  1009    29   9.4  12000     8    7.1      F
17  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z   960    SW    39  86.0  1009    25   9.2  11000     8    7.0      F
18  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z  1020    SW    33  87.8  1009    23   8.9  11000     8    7.0      F
19  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z  1080    SW    36  85.5  1008    23   8.9  11000     8    6.6      F
20  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z  1140    SW    40  86.6  1007    28   8.8  14000     8    6.7      F
21  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z  1200   SSW    39  84.8  1006    28   8.8  13000     8    6.4      F
22  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z  1260   SSW    37  87.7  1005    26   8.0  15000     8    6.1      F
23  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z  1320     S    37  88.4  1003    24   8.0  13000     8    6.2      F
24  3002  60.749  -0.854           BALTASOUND  SCOTLAND    EUROPE      15.0  Day  2020-01-01Z  1380     S    38  89.6  1002    29   7.6  11000     8    6.0      F
25  3005  60.139  -1.183  LERWICK (S. SCREEN)  SCOTLAND    EUROPE      82.0  Day  2019-12-31Z  1380     W    41  89.5  1020    28   7.2  15000     8    5.6      F

当我使用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"

当我在zsh中运行相同的命令时,我没有得到此错误,而得到的只是jq: error: syntax error,unexpected $end (Unix shell quoting issues?) at <top-level>,line 1: to_entries[] | jq: 1 compile error 的预期输出

我对shell脚本的经验不是很丰富。我猜想有一个空字符或其他输入终止符,例如被插入到我的字符串中,但是我无法确认这一点或找到一个好的替代方法。这特别令人讨厌,因为它似乎是特定于shell的。我在大多数测试中都使用的zsh可以很好地处理代码。我只有在尝试运行看到错误的"foo"脚本时才会收到该错误。

最终目的是使可选过滤器正常工作。如果我错过了某个特定于jq的选项,我可以选择其他方式。我尝试使用.sh,但得到了jq 'to_entries[] $ENV.OPTIONAL_FILTER | .value.name' <<< $JSON

jq: error: syntax error,unexpected '$',expecting $end

解决方法

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

在当前情况下,您可以使用--arg命令行选项,例如:

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

您插入${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

有关更多信息,请参见:

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...