bash中是否有“goto”语句?我知道这被认为是不好的做法,但我需要特别“去”。
当前回答
还有一种能力可以达到预期的结果:命令陷阱。例如,它可以用于清理目的。
其他回答
不,没有;关于存在的控制结构的信息,请参见Bash参考手册中的§3.2.4“复合命令”。特别要注意的是,Bash中提到了break和continue,它们不像goto那样灵活,但在Bash中比在某些语言中更灵活,可能会帮助您实现想要的结果。(无论你想要什么……)
你可以在bash中使用case来模拟goto:
#!/bin/bash
case bar in
foo)
echo foo
;&
bar)
echo bar
;&
*)
echo star
;;
esac
生产:
bar
star
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语句。
如果可以将长代码分割成较小的片段,请考虑将其移动到单独的文件中,并从父脚本调用它们。
对于创建类似“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
它确实可能对一些调试或演示需求有用。
我发现Bob Copeland解决方案http://bobcopeland.com/blog/2012/10/goto-in-bash/优雅:
#!/bin/bash
# include this boilerplate
function jumpto
{
label=$1
cmd=$(sed -n "/$label:/{:a;n;p;ba};" $0 | grep -v ':$')
eval "$cmd"
exit
}
start=${1:-"start"}
jumpto $start
start:
# your script goes here...
x=100
jumpto foo
mid:
x=101
echo "This is not printed!"
foo:
x=${x:-10}
echo x is $x
结果:
$ ./test.sh
x is 100
$ ./test.sh foo
x is 10
$ ./test.sh mid
This is not printed!
x is 101