How to perform substring like function in jmespath on a string

6.1k Views Asked by At
  • I would like to know if there is substring function one can leverage in JMESPATH (supported by az cli).
  • I have the below az cli request and I want to just extract the name of the linked subnet with a security group, but unlike other cloud providers azure doesn't store associated resources names the same way.

The name can be extracted in the subnet.id node which looks like below

$ 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"
]
  • I want to only extract "MY_SUBNET" from the the result.

I know there is something called search that is supposed to mimic substring (explained here https://github.com/jmespath/jmespath.jep/issues/5) but it didn't work for me .

$ 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()

Thank you


Edit :

I actually run the request including other elements that's why using substring with bash in a new line is not what I want . here's an example of the full query :

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        

output

{
  "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"
  ]
}
3

There are 3 best solutions below

4
On

If you run Azure CLI in bash, here are string manipulation operations you can do:

Following syntax deletes the longest match of $substring from the front of $string

${string##substring}

In this case, you can retrieve the subnet like this.

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

enter image description here

For more information, you could refer to https://www.thegeekstuff.com/2010/07/bash-string-manipulation/

1
On

I had a similar problem with EventGrid subscriptions and used jq to transform JSON returned by the az command. As a result, you get an JSON array.

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) }]'

The expression Account: (.Account | capture("storageAccounts/(?<name>.+)").name) transforms the original resourceId from the Azure CLI.

# 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"

I've adapted the approach from How to extract a json value substring with jq.

0
On

cut can be used to extract desired values:

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