【问题标题】:How to perform substring like function in jmespath on a string如何在 jmespath 中对字符串执行类似子字符串的函数
【发布时间】:2021-03-16 18:35:13
【问题描述】:
  • 我想知道是否有可以在 JMESPATH 中利用的子字符串函数(由 az cli 支持)。
  • 我有以下 az cli 请求,我只想提取具有安全组的链接子网的名称,但与其他云提供商不同,azure 不会以相同的方式存储关联的资源名称。

可以在 subnet.id 节点中提取名称,如下所示

$ az network nsg show -g my_group -n My_NSG --query "subnets[].id" -o json
[
  "/subscriptions/xxxxxx2/resourceGroups/my_group/providers/Microsoft.Network/virtualNetworks/MY-VNET/subnets/My_SUBNET"
]
  • 我只想从结果中提取 "MY_SUBNET"

我知道有一种叫做搜索的东西应该模仿 子字符串(在这里解释 https://github.com/jmespath/jmespath.jep/issues/5) 但它没有 为我工作。

$ az network nsg show -g my_group -n My_NSG  --query "subnets[].search(id,'@[120:-1]')" -o json
InvalidArgumentValueError: argument --query: invalid jmespath_type value: "subnets[].search(id,'@[120:-1]')"

CLIInternalError: The command failed with an unexpected error. Here is the traceback:
Unknown function: search()

谢谢


编辑:

我实际上运行了包含其他元素的请求,这就是为什么在新行中使用带有 bash 的子字符串不是我想要的。 这是完整查询的示例:

az network nsg show -g "$rg_name" -n "$sg_name" --query "{Name:name,Combo_rule_Ports:to_string(securityRules[?direction==\`Inbound\`].destinationPortRanges[]),single_rule_Ports:to_string(securityRules[?direction==\`Inbound\`].destinationPortRange),sub:subnets[].id,resourceGroup:resourceGroup}" -o json        

输出

{
  "Combo_rule_Ports": "[]",
  "Name": "sg_Sub_demo_SSH",
  "resourceGroup": "brokedba",
  "single_rule_Ports": "[\"22\",\"80\",\"443\"]",
  "sub": [
    "/subscriptions/xxxxxxx/resourceGroups/brokedba/providers/Microsoft.Network/virtualNetworks/CLI-VNET/subnets/Sub_demo"
  ]
}

【问题讨论】:

  • 我怀疑这是因为,与 python 不同,字符串不是 JMESPath 中的字符列表,因此您不能对一个字符串使用切片技术。
  • 那太糟糕了!

标签: substring slice jmespath azure-cli2


【解决方案1】:

如果您在 bash 中运行 Azure CLI,您可以执行以下字符串操作操作:

以下语法从$string的前面删除$substring的最长匹配项

${string##substring}

在这种情况下,您可以像这样检索子网。

var=$(az network nsg show -g nsg-rg -n nsg-name --query "subnets[].id"  -o tsv)
echo ${var##*/}

更多信息,您可以参考https://www.thegeekstuff.com/2010/07/bash-string-manipulation/

【讨论】:

  • 嗨@nancy-xiong,感谢您的建议。该命令确实显示了子网,但是我要求使用 jmespath 选项,因为我还有其他列要显示来自查询的显示以及子网,因为我的输出是表(全部在一行中)。
  • 就像您链接的功能请求一样,我还不知道其他 jmespath 选项。根据我的经验,这是一种在字符串结果中提取子字符串的简单方法,不需要编写复杂的逻辑表达式,然后您可以将结果传递给变量并在 CLI 脚本中的任何地方引用它。
  • 阅读JMESPath Tutorial,似乎我们可以从JSON文档中提取和转换元素,但无法修改或提取JSON中keyvalue值中的子字符串输出,我们只能捕获keyvalue 的完整值。那么,对于这个问题,您还有什么疑问吗?
  • 南希,在我的具体情况下,我可以更新我的 OP。我需要将它们全部放在一行中(这就是我指定 jmespath 方式而不是 shell 的原因)。可以通过子网资源上的名称元素提取子网,但我想在我的 bash 中显示我创建的 nsg 已关联到正确的子网。到目前为止,我有 json 格式的输出,但顺便说一下,它就像 azure 上的所有其他 id 一样难看。 - 我的目标是在表格模式下显示并删除所有不相关的部分,以便可以干净,因为完整的 id 将使行超过屏幕宽度。
【解决方案2】:

cut 可用于提取所需值:

az network nsg show -g my_group -n My_NSG --query "subnets[].id|[0]" -o json | cut -d"/" -f11

【讨论】:

    【解决方案3】:

    我在 EventGrid 订阅中遇到了类似的问题,我使用 jq 来转换 az 命令返回的 JSON。结果,您得到一个 JSON 数组。

    az eventgrid event-subscription list -l $location -g $resourceGroup --query "[].{
         Name:name,
         Container:deadLetterDestination.blobContainerName,
         Account:deadLetterDestination.resourceId
      }" \
      | jq '[.[] | { Name, Container, Account: (.Account | capture("storageAccounts/(?<name>.+)").name) }]'
    
    

    表达式 Account: (.Account | capture("storageAccounts/(?&lt;name&gt;.+)").name) 转换来自 Azure CLI 的原始 resourceId

    # From Azure resourceId...
    "Account": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/my-resource-group/providers/Microsoft.Storage/storageAccounts/mystorageaccount"
    # .. to Azure Storage Account name
    "Account": "mystorageaccount"
    

    我已经适应了 How to extract a json value substring with jq 的方法。

    【讨论】:

    • 感谢您,我需要从资源的 Id 中提取订阅 guid,因此我从 'Id' 中设置了 'SubId',如下所示:[.[] | { Name, Rgrp, InstKey, SubId: (.Id | capture("/subscriptions/(?.[-,0-9,a-f]*)").id) }]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    相关资源
    最近更新 更多