在 Bash 中没有 goto 的情况下该如何处理?

在 Bash 中没有 goto 的情况下该如何处理?

Bash 没有 goto 运算符。我有一个简单的任务,如果不使用 goto 或添加新 proc,我就不知道该如何解决它,这是不可取的。

我有两个条件和一个代码块应该以这种方式工作:

[ 条件 1 ] 如果为真,则运行一些命令并检查 [ 条件 2 ];如果为假,则执行一段代码。

[ 条件 2 ] 如果为真,则不执行相同的代码块;如果为假,则执行相同的代码块。

这个问题能解决吗?还是我必须定义一些 proc 并exit在那里使用?我使用了一个标志变量,但我不喜欢它。

使用 goto 后它看起来会像这样:

[ cond 1 ] || goto label 1
  command
  ...
  command
  [ cond 2 ] && goto label 2

:label 1

block of code

:label 2

类似这样的。

答案1

在 shell 脚本中使用分支的典型方法是通过在主代码块之前声明的函数。但是,我认为这里的根本问题是逻辑问题,而不是 goto。显然是重复的,所以这可以作为函数存在。但同样,为了便于阅读,label 1条件 2 可以变成一个也调用的函数:label 1

#!/bin/bash

label1(){
    echo "label 1 function"
}

check_cond2(){
    if ! [ condition2 ]; then
        label1 arg1 arg2
    fi
}

if [ condition1  ]; then

    command
    ...
    command
    check_cond2
else 
    label1
fi

othercommand2
othercommand3

我注意到在两种情况下都有if false exec a block of codeif false exec a block of code,所以一个想法是先检查这些条件是否都是假的。但是,做出类似的事情if ! [ cond1 ] || ! [ cond2 ]会改变分支逻辑。你仍然可以通过查看此帖子的编辑历史来查看它的伪代码版本。

答案2

当我从 Windows 转到 Linux 桌面时,我有很多预先存在的.BAT文件.CMD需要转换,而且我不打算重写它们的逻辑,所以我成立一种goto在 bash 中执行的方法,因为它自行goto function运行sed以删除脚本中不应该运行的任何部分,然后对其进行全部评估。

以下源代码与原始源代码略有修改,以使其更加健壮

#!/bin/bash

# BAT / CMD goto function
function goto
{
    label=$1
    cmd=$(sed -n "/^:[[:blank:]][[:blank:]]*${label}/{:a;n;p;ba};" $0 | 
          grep -v ':$')
    eval "$cmd"
    exit
}

apt update

# Just for the heck of it: how to create a variable where to jump to:
start=${1:-"start"}
goto "$start"

: start
goto_msg="Starting..."
echo $goto_msg
# Just jump to the label:
goto "continue"

: skipped
goto_msg="This is skipped!"
echo "$goto_msg"

: continue
goto_msg="Ended..."
echo "$goto_msg"

# following doesn't jump to apt update whereas original does
goto update

我一点也不感到内疚,正如 Linus Torvalds 所说:

发件人:Linus Torvalds
主题:回复:2.6.0-test* 有机会吗?
日期:2003 年 1 月 12 日星期日 11:38:35 -0800 (PST)

我认为 goto 很好,而且它们通常比大量缩进更具可读性。尤其如果代码流实际上不是自然缩进的,则为 true(在这种情况下是这样的,所以我不认为使用 goto 是更清晰但一般来说,goto 的可读性会很好)。

当然,在像 Pascal 这样愚蠢的语言中,标签无法描述,goto 可能很糟糕。但这不是 goto 的错,而是语言设计者的脑残。

代码的原始来源 (已修改,以减少错误发生)
引文来源

答案3

您应该将您的放入block_of_code一个函数中并使用一些 if/else:

my_function() {
    block of code
    ...
}

if [[ condition 1 ]] ; then
    command
    ...
    command

    if [[ ! condition 2 ]] ; then
        # label 1
        my_function
    fi

else
    # label 1
    my_function
fi

# label 2    

相关内容