Mic*_*sch 116
如果你使用它来跳过部分大脚本进行调试(参见Karl Nicoll的评论),那么如果false是一个不错的选择(不确定"false"是否始终可用,对我来说它是/ bin/false) :
# ... Code I want to run here ...
if false; then
# ... Code I want to skip here ...
fi
# ... I want to resume here ...
Run Code Online (Sandbox Code Playgroud)
当需要删除调试代码时,困难就出现了."if false"构造非常简单且令人难忘,但是如何找到匹配的?如果您的编辑器允许您阻止缩进,您可以缩进跳过的块(然后您将在完成后将其放回).或者对fi行发表评论,但它必须是你会记得的东西,我怀疑它会非常依赖程序员.
rua*_*akh 72
不,那里没有; 见§3.2.4"复合命令"中的Bash参考手册,了解有关控制结构信息不存在.特别要注意提及break
和continue
,它们不像goto
Bash 那样灵活,但在某些语言中比Bash更灵活,可以帮助你实现你想要的.(无论你想要什么......)
Hub*_*tus 49
它确实可能对某些调试或演示需求有用.
我发现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
Run Code Online (Sandbox Code Playgroud)
结果是:
$ ./test.sh
x is 100
$ ./test.sh foo
x is 10
$ ./test.sh mid
This is not printed!
x is 101
Run Code Online (Sandbox Code Playgroud)
Pau*_*nan 28
您可以case
在bash 中使用来模拟goto:
#!/bin/bash
case bar in
foo)
echo foo
;&
bar)
echo bar
;&
*)
echo star
;;
esac
Run Code Online (Sandbox Code Playgroud)
生产:
bar
star
Run Code Online (Sandbox Code Playgroud)
Lau*_*haw 16
如果您正在测试/调试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"
Run Code Online (Sandbox Code Playgroud)
要使脚本恢复正常,只需删除任何行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"
Run Code Online (Sandbox Code Playgroud)
别名通常不能用于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"
Run Code Online (Sandbox Code Playgroud)
然后你可以export DEBUG=TRUE
在运行脚本之前做.
标签是注释,因此如果禁用我们goto
的(通过设置goto
为:
'no-op),不会导致语法错误,但这意味着我们需要在我们的goto
语句中引用它们.
无论何时使用任何类型的goto
解决方案,您都需要注意,您跳过的代码不会设置您以后依赖的任何变量 - 您可能需要将这些定义移到脚本的顶部,或者只是在一个以上你的goto
陈述.
Set*_*ley 11
虽然其他人已经澄清说goto
bash中没有直接的等价物(并提供了最接近的替代方法,如函数,循环和中断),但我想说明如何使用循环加上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
Run Code Online (Sandbox Code Playgroud)
goto
bash 中没有。
这是一些肮脏的解决方法,使用trap
它只向后跳转:)
#!/bin/bash -e
trap '
echo I am
sleep 1
echo here now.
' EXIT
echo foo
goto trap 2> /dev/null
echo bar
Run Code Online (Sandbox Code Playgroud)
输出:
$ ./test.sh
foo
I am
here now.
Run Code Online (Sandbox Code Playgroud)
这不应该以这种方式使用,而只能用于教育目的。这就是为什么它有效的原因:
trap
就是利用异常处理来实现代码流程的改变。在这种情况下,trap
捕获任何导致脚本退出的内容。该命令goto
不存在,因此会引发错误,通常会退出脚本。此错误被 捕获trap
,并且2>/dev/null
隐藏通常显示的错误消息。
goto 的这种实现显然是不可靠的,因为任何不存在的命令(或任何其他错误,以这种方式)都会执行相同的陷阱命令。特别是,您无法选择要转到哪个标签。
基本上在实际场景中,您不需要任何 goto 语句,它们是多余的,因为对不同位置的随机调用只会使您的代码难以理解。
如果您的代码被调用多次,请考虑使用循环并将其工作流程更改为使用continue
and break
。
如果您的代码自我重复,请考虑编写该函数并根据需要多次调用它。
如果您的代码需要根据变量值跳转到特定部分,请考虑使用case
语句。
如果您可以将长代码分成较小的部分,请考虑将其移动到单独的文件中并从父脚本中调用它们。
该解决方案存在以下问题:
:
label:
上线作为标签的任何地方这是一个固定的(shell-check
干净的)版本:
#!/bin/bash
# GOTO for bash, based upon /sf/answers/2188889391/
function goto
{
local label=$1
cmd=$(sed -En "/^[[:space:]]*#[[:space:]]*$label:[[:space:]]*#/{:a;n;p;ba};" "$0")
eval "$cmd"
exit
}
start=${1:-start}
goto "$start" # GOTO start: by default
#start:# Comments can occur after labels
echo start
goto end
# skip: # Whitespace is allowed
echo this is usually skipped
# end: #
echo end
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
339966 次 |
最近记录: |