BASH - 将数组中的值读入命令
BASH - Read value from array into command
我对 bash 比较陌生,我需要使用 Azure CLI 为 Azure MySQL 服务器实例创建 127 个 VNET 安全规则,这需要规则名称和关联的子网 ID。规则名称是子网名称。我可以将子网名称和 ID 读取到数组中,并且可以看到填充了
的数组
mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup
--vnet-name vnet --query "[].{objectID:id}" -o table)
然后我想 运行 以下命令,以便它使用数组中的每个名称和 ID 创建 127 条规则。
az mysql server vnet-rule create -n <rule name from vnetRULEname> -g resourcegroup -s servername --subnet <subnet ID from vnetRULEid>
将子网名称和 ID 值读入同一个数组会更好吗?
在 bash 脚本中执行此操作的最佳方法是什么?我如何告诉它忽略名为 Name 和 ID 的列 headers 以及名为 GatewaySubnet 的子网?
输出示例(子网名称)
Name
-------------
GatewaySubnet
app-host-001
app-host-002
app-host-003
app-host-004
app-host-005
输出示例(子网 ID)
ObjectID
-----------------------------------------------------------------------------
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/GatewaySubnet
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-001
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-002
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-003
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-004
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-005
运行
#!/bin/bash
mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
echo "These are vnetRULEname: ${vnetRULEname[@]}"
echo "These are vnetRULEids : ${vnetRULEid[@]}"
如我所料,在屏幕上显示两个数组的内容。但是如果我 运行
mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
#echo "These are vnetRULEname: ${vnetRULEname[@]}"
#echo "These are vnetRULEids : ${vnetRULEid[@]}"
sizeofarrays=${#arr[@]}
for (( i=0 ; i < sizeofarrays ; i++ ))
do
az mysql server vnet-rule create --name "${vnetRULEname[$i]}" --resource-group resourcegroup --server server --subnet "${vnetRULEid[$i]}"
done
echo ${arr[@]} ## print all the array
echo ${#arr[@]} ## print its size
我明白了
0
0
非常感谢,
安德鲁
for 循环呢?
echo "These are vnetRULEname: ${vnetRULEname[@]}"
echo "These are vnetRULEids : ${vnetRULEid[@]}"
sizeofarrays=${#arr[@]}
for (( i=0 ; i < sizeofarrays ; i++ ))
do
az mysql server vnet-rule create -n "${vnetRULEname[$i]}" -g resourcegroup -s servername --subnet "${vnetRULEid[$i]}"
done
希望对你有用! :)
编辑:
这就是您获取数组大小和元素的方式
echo ${arr[@]} ## print all the array
echo ${#arr[@]} ## print its size
## so in your case sizeofarray should be equal to ${#arr[@]}
首先,一种在忽略前两个键(对应于 header 行)后正确地同步迭代两个数组的方法:
#!/usr/bin/env bash
mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
# Remove the headers from each
unset 'vnetRULE'{name,id}{'[0]','[1]'}
for idx in "${!vnetRULEname[@]}"; do
name=${vnetRULEname[$idx]}
id=${vnetRULEid[$idx]}
az mysql server vnet-rule create \
-n "$name" \
-g resourcegroup \
-s servername \
--subnet "$id"
done
其次,一种将两条数据读入单个关联数组的方法,将 id 存储为键,将名称存储为值:
#!/usr/bin/env bash
declare -A vnets=( )
{
# consume header lines
read <&3; read <&3; read <&4; read <&4
while IFS= read -r name <&3 && IFS= read -r id <&4; do
vnets[$id]=$name
done
} 3< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table) 4< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
for id in "${!vnets[@]}"; do
name=${vnets[$id]}
az mysql server vnet-rule create \
-n "$name" \
-g resourcegroup \
-s servername \
--subnet "$id"
done
...当然,如果你能做到,你可以直接在while read
循环中调用命令,根本不需要存储数组:
{
# consume header lines
read <&3; read <&3; read <&4; read <&4
while IFS= read -r name <&3 && IFS= read -r id <&4; do
az mysql server vnet-rule create \
-n "$name" \
-g resourcegroup \
-s servername \
--subnet "$id"
done
} 3< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table) 4< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
我对 bash 比较陌生,我需要使用 Azure CLI 为 Azure MySQL 服务器实例创建 127 个 VNET 安全规则,这需要规则名称和关联的子网 ID。规则名称是子网名称。我可以将子网名称和 ID 读取到数组中,并且可以看到填充了
的数组mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup
--vnet-name vnet --query "[].{objectID:id}" -o table)
然后我想 运行 以下命令,以便它使用数组中的每个名称和 ID 创建 127 条规则。
az mysql server vnet-rule create -n <rule name from vnetRULEname> -g resourcegroup -s servername --subnet <subnet ID from vnetRULEid>
将子网名称和 ID 值读入同一个数组会更好吗?
在 bash 脚本中执行此操作的最佳方法是什么?我如何告诉它忽略名为 Name 和 ID 的列 headers 以及名为 GatewaySubnet 的子网?
输出示例(子网名称)
Name
-------------
GatewaySubnet
app-host-001
app-host-002
app-host-003
app-host-004
app-host-005
输出示例(子网 ID)
ObjectID
-----------------------------------------------------------------------------
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/GatewaySubnet
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-001
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-002
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-003
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-004
/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/resourcegroup/providers/Microsoft.Network/virtualNetworks/vnet/subnets/app-host-005
运行
#!/bin/bash
mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
echo "These are vnetRULEname: ${vnetRULEname[@]}"
echo "These are vnetRULEids : ${vnetRULEid[@]}"
如我所料,在屏幕上显示两个数组的内容。但是如果我 运行
mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
#echo "These are vnetRULEname: ${vnetRULEname[@]}"
#echo "These are vnetRULEids : ${vnetRULEid[@]}"
sizeofarrays=${#arr[@]}
for (( i=0 ; i < sizeofarrays ; i++ ))
do
az mysql server vnet-rule create --name "${vnetRULEname[$i]}" --resource-group resourcegroup --server server --subnet "${vnetRULEid[$i]}"
done
echo ${arr[@]} ## print all the array
echo ${#arr[@]} ## print its size
我明白了
0
0
非常感谢,
安德鲁
for 循环呢?
echo "These are vnetRULEname: ${vnetRULEname[@]}"
echo "These are vnetRULEids : ${vnetRULEid[@]}"
sizeofarrays=${#arr[@]}
for (( i=0 ; i < sizeofarrays ; i++ ))
do
az mysql server vnet-rule create -n "${vnetRULEname[$i]}" -g resourcegroup -s servername --subnet "${vnetRULEid[$i]}"
done
希望对你有用! :)
编辑:
这就是您获取数组大小和元素的方式
echo ${arr[@]} ## print all the array
echo ${#arr[@]} ## print its size
## so in your case sizeofarray should be equal to ${#arr[@]}
首先,一种在忽略前两个键(对应于 header 行)后正确地同步迭代两个数组的方法:
#!/usr/bin/env bash
mapfile -t vnetRULEname < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table)
mapfile -t vnetRULEid < <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
# Remove the headers from each
unset 'vnetRULE'{name,id}{'[0]','[1]'}
for idx in "${!vnetRULEname[@]}"; do
name=${vnetRULEname[$idx]}
id=${vnetRULEid[$idx]}
az mysql server vnet-rule create \
-n "$name" \
-g resourcegroup \
-s servername \
--subnet "$id"
done
其次,一种将两条数据读入单个关联数组的方法,将 id 存储为键,将名称存储为值:
#!/usr/bin/env bash
declare -A vnets=( )
{
# consume header lines
read <&3; read <&3; read <&4; read <&4
while IFS= read -r name <&3 && IFS= read -r id <&4; do
vnets[$id]=$name
done
} 3< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table) 4< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)
for id in "${!vnets[@]}"; do
name=${vnets[$id]}
az mysql server vnet-rule create \
-n "$name" \
-g resourcegroup \
-s servername \
--subnet "$id"
done
...当然,如果你能做到,你可以直接在while read
循环中调用命令,根本不需要存储数组:
{
# consume header lines
read <&3; read <&3; read <&4; read <&4
while IFS= read -r name <&3 && IFS= read -r id <&4; do
az mysql server vnet-rule create \
-n "$name" \
-g resourcegroup \
-s servername \
--subnet "$id"
done
} 3< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{name:name}" -o table) 4< <(az network vnet subnet list -g resourcegroup --vnet-name vnet --query "[].{objectID:id}" -o table)