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 code
和if 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