bash中是否有“goto”语句?我知道这被认为是不好的做法,但我需要特别“去”。


当前回答

不,没有;关于存在的控制结构的信息,请参见Bash参考手册中的§3.2.4“复合命令”。特别要注意的是,Bash中提到了break和continue,它们不像goto那样灵活,但在Bash中比在某些语言中更灵活,可能会帮助您实现想要的结果。(无论你想要什么……)

其他回答

如果您正在测试/调试一个bash脚本,并且只想跳过一个或多个代码部分,那么这里有一种非常简单的方法,以后也很容易找到并删除(与上面描述的大多数方法不同)。

#!/bin/bash

echo "Run this"

cat >/dev/null <<GOTO_1

echo "Don't run this"

GOTO_1

echo "Also run this"

cat >/dev/null <<GOTO_2

echo "Don't run this either"

GOTO_2

echo "Yet more code I want to run"

要使脚本恢复正常,只需删除GOTO中的任何行。

我们还可以通过添加goto命令作为别名来修饰这个解决方案:

#!/bin/bash

shopt -s expand_aliases
alias goto="cat >/dev/null <<"

goto GOTO_1

echo "Don't run this"

GOTO_1

echo "Run this"

goto GOTO_2

echo "Don't run this either"

GOTO_2

echo "All done"

别名在bash脚本中通常不起作用,因此我们需要使用shopt命令来解决这个问题。

如果你想启用/禁用你的goto,我们需要更多一点:

#!/bin/bash

shopt -s expand_aliases
if [ -n "$DEBUG" ] ; then
  alias goto="cat >/dev/null <<"
else
  alias goto=":"
fi

goto '#GOTO_1'

echo "Don't run this"

#GOTO1

echo "Run this"

goto '#GOTO_2'

echo "Don't run this either"

#GOTO_2

echo "All done"

然后在运行脚本之前执行export DEBUG=TRUE。

标签是注释,因此如果禁用goto(通过将goto设置为':' no-op)不会导致语法错误,但这意味着我们需要在goto语句中引用它们。

无论何时使用任何类型的goto解决方案,你都需要小心,你跳过的代码不会设置你以后依赖的任何变量——你可能需要将这些定义移动到脚本的顶部,或者只是在你的goto语句之上。

不,没有;关于存在的控制结构的信息,请参见Bash参考手册中的§3.2.4“复合命令”。特别要注意的是,Bash中提到了break和continue,它们不像goto那样灵活,但在Bash中比在某些语言中更灵活,可能会帮助您实现想要的结果。(无论你想要什么……)

尽管其他人已经澄清了bash中没有直接的goto等价(并提供了最接近的替代方法,如函数、循环和break),但我想说明如何使用循环加break来模拟特定类型的goto语句。

我发现这种方法最有用的情况是,如果某些条件不满足,我需要返回到一段代码的开头。在下面的例子中,while循环将一直运行,直到ping停止向测试IP发送数据包。

#!/bin/bash

TestIP="8.8.8.8"

# Loop forever (until break is issued)
while true; do

    # Do a simple test for Internet connectivity
    PacketLoss=$(ping "$TestIP" -c 2 | grep -Eo "[0-9]+% packet loss" | grep -Eo "^[0-9]")

    # Exit the loop if ping is no longer dropping packets
    if [ "$PacketLoss" == 0 ]; then
        echo "Connection restored"
        break
    else
        echo "No connectivity"
    fi
done

你可以在bash中使用case来模拟goto:

#!/bin/bash

case bar in
  foo)
    echo foo
    ;&

  bar)
    echo bar
    ;&

  *)
    echo star
    ;;
esac

生产:

bar
star

还有一种能力可以达到预期的结果:命令陷阱。例如,它可以用于清理目的。