jq选择比较不区分大小写。

3

我有一个看起来像下面这样的json文件:

{
    "items": [
        {
            "id": "some_id_1",
            "name": "job_get_re_Log",
            "type": "standard",
            "workspace": {
                "id": "some_id_2",
                "name": "Shared",
                "description": "",
                "type": "custom",
                "environment": {
                    "id": "some_id_3",
                    "name": "DEV"
                }
            }
        }
    ]
}

为了获取id(some_id_1),我运行以下命令:
name="job_get_re_log"
workspace="Shared"
environment="DEV"

id=$(echo $jsonFile | jq -r ".items[] | select(.name == \"$name\" and .workspace.name == \"$workspace\" and .workspace.environment.name == \"$environment\").id")

echo "$id"

正如您所看到的,变量名为“job_get_re_log”,但在JSON中的名称为“job_get_re_Log”(大写L)。这最终会失败并返回空值,因为它正在寻找一个完全匹配。

我该如何修改选择命令以进行比较而不考虑大小写(不区分大小写)?


1
顺便提一下,echo $jsonFile 本身就有 bug;如果你的文件包含 "name": " * ",那么 * 将被替换为当前目录中文件名的列表。始终引用您的扩展:echo "$jsonFile" - Charles Duffy
1
足够符合标准的 echo 版本即使没有 -e 也会尝试展开反斜杠;当设置了 posixxpg_echo 运行时标志时,bash 内置版本也是如此。因此,当您想要确保数据被准确表示时,最好完全避免使用 echo,而改用类似 printf '%s\n' "$jsonFile" 的东西。 - Charles Duffy
1
无论如何 - 如果你阅读https://stedolan.github.io/jq/manual/,你会发现jq有`ascii_downcase`和`ascii_upcase`函数。对这两个字符串执行此操作,然后你就完成了。 - Charles Duffy
1
(另外,最好将您的jq代码作为常量字符串,并使用jq --arg name“$name”--arg environment“$environment”传递$name$environment,以使值与代码分离; 这样就不能使用恶意名称进行注入攻击; 为此,--arg name "${name,,}"与支持该扩展的新版本bash一起使用,您只需要将.name转换为小写,而不是$name在jq中) - Charles Duffy
感谢您提供的所有信息!这真的很有帮助。 - o.o
2个回答

3

如果要使用test/1来检查忽略大小写的相等性,您需要锚定正则表达式字符串。假设$name没有特殊的正则表达式字符:

jq -r --arg w "$workspace" --arg e "$environment" --arg n "$name" '
  .items[]
  | select( (.name | test("^\($n)$"; "i")) and
            (.workspace.name == $w) and
            (.workspace.environment.name == $e)) 
  | .id'

使用test/1的目的当然是处理ASCII范围之外的排版情况,例如:

$ jq 'test("Å";"i")' <<< '"å"'
true

正如@OguzIsmail所指出的那样,如果您希望在$name可能包含正则表达式特殊字符的情况下使用test,则可以使用\E转义机制,例如:
$ jq 'test("\\Q.\\E")' <<< '"a"'
false

你不需要手动去除正则表达式 https://github.com/kkos/oniguruma/blob/master/doc/SYNTAX.md#0-onig_syn_op2_esc_capital_q_quote-enable-qe - oguz ismail
1
@OguzIsmail - 谢谢,我不知道那个。 - peak

2

使用test()函数和if ... then ... else语句:

<file jq -r --arg w "$workspace" --arg e "$environment" --arg n "$name" \
      '.items[] | if ((.name | test($n; "i")) and (.workspace.name == $w) and (.workspace.environment.name == $e)) then .id else empty end'

使用给定的标志"i"test进行不区分大小写的搜索。


1
+1,但是在字符串相等性测试的地方使用正则表达式测试是我不太确定的事情。将两个字符串都转换为小写并进行简单的相等比较是否更少出错?如果名称是 fooproject+extensionA,您不希望 + 具有其正则表达式含义。 - Charles Duffy
我认为这个命令有一个 bug。当我传递 "job_get_re" 时,它仍然匹配并返回 "some_id_1",但实际上不应该这样。它应该匹配整个单词。 - o.o
可以在开头添加一个 ^,在结尾添加一个 $ 来进行锚定。更大的问题是正确的转义。 - Charles Duffy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接