将同一命令的每个输出保存在不同的变量中

ph3*_*3ro 0 bash shell-script environment-variables

#!/bin/bash

SERVERLABEL=( 11011-22022 33033-44044-10101 55055-10001-20002 )

    for vmlabel in "${SERVERLABEL[@]}"
    do 
        linode-cli linodes list | grep $vmlabel | grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
    done
Run Code Online (Sandbox Code Playgroud)

上面是我的脚本。我想要做的是将每个虚拟机的 ipv4 保存在不同的环境变量中,例如

ipv4_11011-22022
ipv4_33033-44044-10101
ipv4_55055-10001-20002
Run Code Online (Sandbox Code Playgroud)

我是 bash 脚本新手,有人可以帮助我吗

Gil*_*not 5

使用关联数组

#!/bin/bash

SERVERLABEL=( 11011-22022 33033-44044-10101 55055-10001-20002 )

declare -A ips # declare an associative array explicitly 

for vmlabel in "${SERVERLABEL[@]}"
do 
    ips[ipv4_$vmlabel]=$(
        linode-cli linodes list |
            grep -F -- "$vmlabel" |
            grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
    )
done
Run Code Online (Sandbox Code Playgroud)

您可以减少这个HUDGE正则表达式

linode-cli linodes list |
    grep -F -- "$vmlabel" |
    perl -MRegexp::Common -lne 'print for /$RE{net}{IPv4}/g'
Run Code Online (Sandbox Code Playgroud)

更具可读性和可维护性,不是吗?

或者甚至跳过它本身能够完成的grep事情。perl

linode-cli linodes list |
    perl -MRegexp::Common -lnse '
        if (/\Q$vmlabel\E/) {
            print for /$RE{net}{IPv4}/g
        }' -- -vmlabel="$vmlabel"
Run Code Online (Sandbox Code Playgroud)

更进一步,用perl(或任何适当的编程语言)完成整个事情bash也将使对单次调用的输出进行更严格的解析变得更容易linode-cli,并使其更加可靠和高效。

显示获取到的数据

printf '%s\n' "${!ips[@]}"                     # keys
printf '%s\n' "${ips[@]}"                      # values
printf '%s\n' "${ips[ipv4_55055-10001-20002]}" # display only one key/value pair
Run Code Online (Sandbox Code Playgroud)

请注意grepperl对 进行子字符串匹配$vmlabel,因此 agrep -F -- 11011-22022将匹配包含例如11011-22022包含的任何行。211011-220221您可能需要添加-w选项来grep防范它。