【问题标题】:Why is my BASH compiler skipping over my code?为什么我的 BASH 编译器会跳过我的代码?
【发布时间】:2022-08-14 09:12:38
【问题描述】:

我写了一个for 循环来获取尚未安装的工具的数量。这是我的代码:

#!/bin/bash

DIALOG_INSTALLED=$(which dialog)
BREW_INSTALLED=$(which brew)
TELNET_INSTALLED=$(which telnet)

UNINSTALLED_TOOLS=0

for installed_for in $DIALOG_INSTALLED $BREW_INSTALLED $TELNET_INSTALLED; do
    if [[ -z $installed_for ]]; then
        let \"$UNINSTALLED_TOOLS+=1\"
    fi
done

echo $UNINSTALLED_TOOLS

我的问题是,当我去运行代码时,$UNINSTALLED_TOOLS 仍然等于 0。要找到问题的根源,$UNINSTALLED_TOOLS=3for 循环之前和之后。这两个调整都将$UNINSTALLED_TOOLS 的最终值更改为3。现在我知道问题出在for 循环中。就好像代码跳过了for 循环。我没有收到任何语法错误,所以我很困惑。

任何帮助表示赞赏。

    标签: bash for-loop


    【解决方案1】:

    假设找不到dialog。变量替换后,你得到:

    for installed_for in /usr/local/bin/brew /usr/local/bin/telnet; do
    

    所以$installed_for 永远没有机会成为一个空字符串。一旦你用空字符串循环for,你的let也是不正确的,因为在替换之后你有

    let 0+=1
    

    这没有任何意义。所以:

    DIALOG_INSTALLED=$(which dialog)
    BREW_INSTALLED=$(which brew)
    TELNET_INSTALLED=$(which telnet)
    
    INSTALLED_ARRAY=("$DIALOG_INSTALLED" "$BREW_INSTALLED" "$TELNET_INSTALLED")
    UNINSTALLED_TOOLS=0
    
    for installed_for in "${INSTALLED_ARRAY[@]}"; do
        if [[ -z "$installed_for" ]]; then
            let UNINSTALLED_TOOLS+=1
        fi
    done
    echo "$UNINSTALLED_TOOLS"
    

    【讨论】:

      【解决方案2】:
      for installed_for in $DIALOG_INSTALLED $BREW_INSTALLED $TELNET_INSTALLED; do
      

      这不是超过 3 个元素的循环;这是一个循环,无论变量$DIALOG_INSTALLED $BREW_INSTALLED $TELNET_INSTALLED 扩展到多少单词。因此,例如,如果您有 /usr/bin/dialog/bin/telnet,但 brew 已卸载,那么 for 将是 2 个元素的循环,就像您键入

      for installed_for in /usr/bin/dialog  /bin/telnet; do
      

      特别是,[[ -z $installed_for ]] 永远不会是真的。

      您可能想要引用它们,以便如果它们中的任何一个为空,for 循环仍将其作为空字符串进行迭代:

      for installed_for in "$DIALOG_INSTALLED" "$BREW_INSTALLED" "$TELNET_INSTALLED"; do
      

      另外,let "$UNINSTALLED_TOOLS+=1" 是错误的。它在评估算术之前扩展了$UNINSTALLED_TOOLS,所以它变成了类似于let 0+=1,这是无效的。它应该是let "UNINSTALLED_TOOLS+=1"

      【讨论】:

        【解决方案3】:

        如果您只想计算已卸载的工具,您可以执行以下操作

        w() { which -s "$1"; echo $?; }
        uninstalled_tools=$(( $(w dialog) + $(w brew) + $(w telnet) ))
        

        不需要循环。只需让函数回显值和总和。

        【讨论】:

          【解决方案4】:

          你最好使用这样的循环:

          for i in dialog brew telnet; do
              command -v "$i" &>/dev/null ||
              ((++missing))
          done
          
          echo "${missing:-0}" missing dependencies
          

          您可以为错误消息等添加逻辑。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-06-03
            • 1970-01-01
            • 2017-05-02
            • 2021-08-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多