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


当前回答

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

#!/bin/bash

case bar in
  foo)
    echo foo
    ;&

  bar)
    echo bar
    ;&

  *)
    echo star
    ;;
esac

生产:

bar
star

其他回答

对于创建类似“goto”的东西,我的想法是使用带大小写的select并赋值一个变量,然后在if语句中检查该变量。不完美,但在某些情况下可能有帮助

例子:

#!/usr/bin/env bash

select goto in Ubuntu Debian Quit ; do
    case $goto in
        Ubuntu) { CHOICE="Ubuntu" ; break ; } ;;
        Debian) { CHOICE="Debian" ; break ; } ;;
        Quit)   { echo "Bye" ; exit ; } ;;
        *)      { echo "Invalid selection, please try again..." ; } ;;
    esac
done

if [ "$CHOICE" == "Ubuntu" ]; then
    echo "I'm in Ubuntu"
fi

if [ "$CHOICE" == "Debian" ]; then
    echo "I'm in Debian"
fi

为什么没有人直接使用函数呢? 顺便说一句,处理函数比制作新东西容易得多

我的风格:

#!/bin/bash

# Your functions
function1 ()
{
    commands
}

function2 ()
{
    commands
}
    :
    :

functionn ()
{
    commands
}

# Execute 1 to n in order
for i in {1..n}
    do
        function$i
    done

# with conditions
for i in {1..n}
    do
        [ condition$i ] && function$i
    done

# Random order
function1
functionn
function5
    :
    :
function3

以上风格的例子:

#!/bin/bash

# Your functions
function1 ()
{
    echo "Task 1"
}

function2 ()
{
    echo "Task 2"
}

function3 ()
{
    echo "Task 3"
}

function1
function3
function2

输出:

Task 1
Task 3
Task 2

缺点:

有组织地编写脚本。 问题少,不容易出错。 你可以在已有的函数中创建函数。 来回移动没有任何问题。

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

一个简单的可搜索的goto,用于在调试时注释掉代码块。

GOTO=false
if ${GOTO}; then
    echo "GOTO failed"
    ...
fi # End of GOTO
echo "GOTO done"

结果是-> GOTO done

bash中没有goto。

这里有一些肮脏的工作方法,使用陷阱只向后跳转:)

#!/bin/bash -e
trap '
echo I am
sleep 1
echo here now.
' EXIT

echo foo
goto trap 2> /dev/null
echo bar

输出:

$ ./test.sh 
foo
I am
here now.

不应该以这种方式使用,而只能用于教育目的。以下是这种方法有效的原因:

Trap是使用异常处理来实现代码流中的更改。 在本例中,该陷阱将捕获导致脚本退出的任何内容。goto命令不存在,因此会抛出一个错误,该错误通常会退出脚本。此错误被trap捕获,2>/dev/null隐藏了通常显示的错误消息。

goto的这种实现显然是不可靠的,因为任何不存在的命令(或任何其他错误)都会执行相同的trap命令。特别是,您无法选择要使用哪个标签。


基本上在实际场景中,你不需要任何goto语句,它们是多余的,因为随机调用不同的地方只会让你的代码难以理解。

如果您的代码被多次调用,那么考虑使用loop并将其工作流更改为使用continue和break。

如果您的代码重复,请考虑编写函数并尽可能多次地调用它。

如果您的代码需要根据变量值跳转到特定的部分,那么可以考虑使用case语句。

如果可以将长代码分割成较小的片段,请考虑将其移动到单独的文件中,并从父脚本调用它们。