bash 无法识别 for 循环中字符串数组的每个元素的 if 条件

bash 无法识别 for 循环中字符串数组的每个元素的 if 条件

目标

我用来whiptail让用户将密码插入到与envsubst某些模板文件结合使用的文件中。

whiptail清单

为了渲染内容,whiptail我使用以下内容:

declare -A availableServices=(
    [grafana]="Grafana Dashboard"
    [influxdb]="InfluxDB v1.x TSDB"
    [node-red]="Node-RED Flow UI"
    [portainer]="Portainer Container Mgmt"
)

# Render TUI
function askGenerateCredential() {
    local message="Set Password for particular Service\n
                Press <SPACEBAR> to Select \n
                Press <Enter> to Skip
                "
    local arglist=()
    
    # Generate a String for Whiptail Checkboxes
     # FORMAT: "<INDEX> <DESCRIPTION> <OFF>"
    for index in "${!availableServices[@]}";
    do
        # Default all Services are NOT-Selected (OFF)
        arglist+=("$index" "${availableServices[$index]}" "OFF")
    done
    SELECTED_SERVICES+=$($WHIPTAIL --title "Available Services within Populo" \
                --notags --separate-output \
                --ok-button Next \
                --nocancel \
                --checklist "$message" $LINES $COLUMNS $(( LINES - 12 )) \
                -- "${arglist[@]}" \
                3>&1 1>&2 2>&3)
}

SELECTED_SERVICES一个声明为的数组

declare -a SELECTED_SERVICES=()

渲染效果很好,但是if else我的脚本中有一个特定条件,无法根据上面数组中选定的服务执行特定命令。

askGenerateCredential
if [ -z "$SELECTED_SERVICES" ]; then
    echo "No Services were selected. Exiting..."
    exit 1
else
    for service in "${SELECTED_SERVICES}";
    do
        if [ "$service" == "influxdb" ]; then
            echo "Setting Credentials for InfluxDB"
            setInfluxDBCredentials
        elif [ "$service" == "grafana" ]; then
            echo "Setting Credentials for Grafana"
            setGrafanaCredentials
        elif [ "$service" == "node-red" ]; then
            echo "Setting Credentials for node-RED"
            setNodeRedCredentials
        elif [ "$service" == "portainer" ]; then
            echo "Setting Credential for Portainer"
            setPortainerCredentials
        fi
    done
fi

添加上述块后,0当我通过 UI 选择多个值时,我的脚本将退出并显示代码whiptail。相反,当我在 UI 中仅选择一个值时,就会调用相应的函数。

我在这里做错了什么?我希望根据service变量调用相应的函数而不退出脚本。

代码

#!/bin/env bash

WHIPTAIL=$(which whiptail)

if [ -z $WHIPTAIL ]
then
    echo "This script requires whiptail to render the TUI."
    exit 1
fi

declare -a SELECTED_SERVICES=()

LINES=$(tput lines)
COLUMNS=$(tput cols)


declare -A availableServices=(
    [grafana]="Grafana Dashboard"
    [influxdb]="InfluxDB v1.x TSDB"
    [node-red]="Node-RED Flow UI"
    [portainer]="Portainer Container Mgmt"
)

function askGenerateCredential() {
    local message="Set Password for particular Service\n
                Press <SPACEBAR> to Select \n
                Press <Enter> to Skip
                "
    local arglist=()
    
    # Generate a String for Whiptail Checkboxes
     # FORMAT: "<INDEX> <DESCRIPTION> <OFF>"
    for index in "${!availableServices[@]}";
    do
        # Default all Services are NOT-Selected (OFF)
        arglist+=("$index" "${availableServices[$index]}" "OFF")
    done
    SELECTED_SERVICES+=$($WHIPTAIL --title "Available Services within Populo" \
                --notags --separate-output \
                --ok-button Next \
                --nocancel \
                --checklist "$message" $LINES $COLUMNS $(( LINES - 12 )) \
                -- "${arglist[@]}" \
                3>&1 1>&2 2>&3)
}

function setInfluxDBCredential() {
    echo "set admin password env var for influxdb"
}

function setGrafanaCredential() {
    echo "set admin password env var for grafana"
}

function setNodeRedCredential() {
    echo "set admin password env var for node-REd"
}

function setPortainerCredential() {
    echo "set password file for portainer"
}

askGenerateCredential
if [ -z "$SELECTED_SERVICES" ]; then
    echo "No Services were selected. Exiting..."
    exit 1
else
    for service in "${SELECTED_SERVICES}";
    do
        if [ "$service" == "influxdb" ]; then
            echo "Setting Credentials for InfluxDB"
            setInfluxDBCredentials
        elif [ "$service" == "grafana" ]; then
            echo "Setting Credentials for Grafana"
            setGrafanaCredentials
        elif [ "$service" == "node-red" ]; then
            echo "Setting Credentials for node-RED"
            setNodeRedCredentials
        elif [ "$service" == "portainer" ]; then
            echo "Setting Credential for Portainer"
            setPortainerCredentials
        fi
    done
fi

编辑

${SELECTED_SERVICES[@]}根据建议,我在 for 循环中尝试并添加了一个echo "$service"能够循环数组的循环,但是if条件没有被触发。

答案1

我相信你的函数中的逻辑askGenerateCredential()并没有做你想做的事情。目前,whiptail 命令的整个输出都作为单个元素添加到数组中。如果您希望在换行符处拆分多个元素,您应该将其更改为如下所示:

askGenerateCredential() {
    local message="Set Password for particular Service\n
                Press <SPACEBAR> to Select \n
                Press <Enter> to Skip
                "
    local arglist=()
    
    # Generate a String for Whiptail Checkboxes
     # FORMAT: "<INDEX> <DESCRIPTION> <OFF>"
    for index in "${!availableServices[@]}";
    do
        # Default all Services are NOT-Selected (OFF)
        arglist+=("$index" "${availableServices[$index]}" "OFF")
    done
    readarray -t SELECTED_SERVICES < <("$WHIPTAIL" --title "Available Services within Populo" \
                --notags --separate-output \
                --ok-button Next \
                --nocancel \
                --checklist "$message" "$LINES" "$COLUMNS" $(( LINES - 12 )) \
                -- "${arglist[@]}" \
                3>&1 1>&2 2>&3)
}

4.2 Bash 内置命令


此外,您还SELECTED_SERVICES作为变量而不是数组进行调用。

你需要改变:

for service in "${SELECTED_SERVICES}"

到:

for service in "${SELECTED_SERVICES[@]}"

按照原样,您将仅扩展数组的第一个元素。然而,当您编写的代码时,SELECTED_SERVICES只会收到一个元素。

6.7 数组


另外,使用 case 可能比 if/elif 结构更好。就像是:

case $service in
    influxdb)   echo "Setting Credentials for InfluxDB"; setInfluxDBCredentials;;
    grafana)    echo "Setting Credentials for Grafana"; setGrafanaCredentials;;
    node-red)   echo "Setting Credentials for node-RED"; setNodeRedCredentials;;
    portainer)  echo "Setting Credential for Portainer"; setPortainerCredentials;;
    *)  echo "Error; unknown option: $service" >&2;;
esac

相关内容