如何创建 bash 脚本,替代“goto”和“labels”

如何创建 bash 脚本,替代“goto”和“labels”

批量:

@echo off
:step1
if exist "file1.txt" (GOTO step2) ELSE (GOTO X)
:step2
if exist "file2.txt" (GOTO Z) ELSE (GOTO Y)

:X
run the script from the beginning and file1.txt and file2.txt are created and the rest of the script is executed
:Y
run the commands to file1.txt and run the rest of the script
:Z
run the commands to file2.txt and run the rest of the script

我知道 bash 中不存在“goto”和“标签”,但是在 bash 中执行类似于上述操作的替代方法是什么?

试图:

#!/bin/bash
if [ -e file1.txt ]; then
        echo "file1.txt ok"
            if [ -e file2.txt ]; then
                echo "file2.txt ok"
                alternative to goto label Z
            else
                alternative to goto label Y
            fi
    else
        echo "file1.txt doesn't exist"
        alternative to goto label X
fi

PD:仅用于传达想法的基本脚本

批处理(也应该执行 bash)做什么(重要的是避免混淆):

完整脚本运行一些命令并创建文件 file1.txt 和 file2.txt。因此,由于脚本很长并且可能在某个时刻被中断,所以我想要的是从中断的地方开始脚本。这就是验证的目的:

  • 如果 file1.txt 存在 (Y),则脚本已经创建它,并继续检查 file2.txt (Z) 是否存在(脚本的另一部分)。
  • 如果 file2.txt 存在(Z),则意味着命令从该点开始
  • 如果 file2.txt (Z) 不存在,但 file1.txt (Y) 存在,则意味着脚本在创建 file1.txt (Y) 和 file2.txt (Z) 之间的某个位置被中断,然后从 file1 开始。文本(是)
  • 如果 file1.txt (Y) 和 file2.txt (Z) 都不存在,那么我必须从脚本 (X) 的开头开始

答案1

在确切地知道批处理脚本应该做什么之后,我将首先对其进行一些简化:

@echo off
if exist "file1.txt" goto skip_part1
run the script from the beginning and file1.txt and file2.txt are created and the rest of the script is executed
:skip_part1
if exist "file2.txt" goto skip_part2
run the commands to file1.txt and run the rest of the script
:skip_part2
run the commands to file2.txt and run the rest of the script

可以等效地写为:

@echo off
if not exist "file1.txt" (
  run the script from the beginning and file1.txt and file2.txt are created and the rest of the script is executed
)
if not exist "file2.txt" (
  run the commands to file1.txt and run the rest of the script
)
run the commands to file2.txt and run the rest of the script

这可以直接翻译为以下 bash 脚本:

#!/bin/bash
if [ ! -e file1.txt ]; then
  run the script from the beginning and file1.txt and file2.txt are created and the rest of the script is executed
fi
if [ ! -e file2.txt ]; then
  run the commands to file1.txt and run the rest of the script
fi
run the commands to file2.txt and run the rest of the script

答案2

该脚本几乎可以自动转换,尽管看起来很奇怪!步骤是

  1. 在脚本开头插入
_current_label="_first_state"
main_function(){
case "$_current_label" in
("_first_state")
  1. 在脚本末尾附加
_current_state="_the_end"
return
;;
esac
}
while [ "$current_state" != "_the_end" ] ; do main_function ; done
  1. 分别:label改为
_current_label="label"
;;
("label")
  1. 分别goto skip_part1改为
_current_label="skip_part1"
return

所以你的脚本看起来像

#!/bin/bash
_current_label="_first_state"
main_function(){
case "$_current_label" in
("_first_state")
_current_label="step1"
;;
("step1")
if [ -e file1.txt ]; then
        echo "file1.txt ok"
        _current_label="step2"
        return
else
        echo "file1.txt doesn't exist"
        _current_label="X"
        return
fi
_current_label="step2"
;;
("step2")
            if [ -e file2.txt ]; then
                echo "file2.txt ok"
                _current_label="Z"
                return
            else
                _current_label="Y"
                return
            fi
           _current_label="X"
;;
("X")
run the script from the beginning and file1.txt and file2.txt are created and the rest of the script is executed
_current_label="Y"
;;
("Y")
run the commands to file1.txt and run the rest of the script
_current_label="Z"
;;
("Z")
run the commands to file2.txt and run the rest of the script
_current_label=""
return
;;
esac
}
while [ "$current_label" != "" ] ; do main_function ; done

这个想法是构建一个非常简单的有限状态机。每个状态都是 case 语句中的一个标签。在每个状态下,您运行代码,直到goto在原始代码中遇到 a ,此时您设置全局值_current_label并返回,或者遇到标签。然后,循环将导致 case 语句从这个新标签开始再次运行。

请注意,“自动”翻译会放入一些永远无法执行的代码。

这种“自动”翻译不处理callorstart语句。

如果您有一个工具可以缩进生成的脚本,我强烈建议您运行它!

相关内容