shell实现状态机(state machine)示例

版权声明:原创作品转载必须注明出处 https://blog.csdn.net/u013390088/article/details/82223770

shell 还是很强大很实用的一种工具的

  1. 我对这种状态机的理解就是一个操作的闭环,即程序在和用户的交互过程中无论用户做出什么选择,程序总是能给出正常的响应——包括错误/警告提示。比如从一个菜单选择开始,进入其中一个选项后选择退出或者下一步都能看到一个响应界面,而不出现程序卡死或异常退出的现象。
  2. 实现这种状态机主要用到case语句来做跳转
  3. 这里的示例利用表示状态的STATE变量对10取余来实现对跳转过程的划分阶段的功能——0、10-19、20-29分别表示三个阶段
  4. 简单示例如下
#!/bin/bash

...

# 假设一个实现选择下一步和上一步的函数go,其返回是否进入下一步或是进入上一步
go(){
    xxx
}
# STATE表示当前的状态
STATE=10
# LASTSTATE表示上一次完成一个循环后的状态
# 有时两个状态来回切换了,但又没有做修改,利用整个LASTSTATE和STATE作比较可以跳过一些不必要的操作
LASTSTATE=0
while :; do
        case $STATE in
        0) # 当前脚本以10为返回值表示正常退出,一般调用该脚本的程序对整个返回值10视为正常完成任务的信号
            exit 10
            ;;
        10) # 第一个阶段开始
            echo '状态$STATE ...'
            ;;
        11) # 第一个阶段的第一步
            # 选择是否进入下一步
            res=go
            if [ $res == 'true' ];then
                echo '由于xxx , 直接跳转到STATE=20,**进行阶段的切换**'
                STATE=20
                continue
            fi
            echo '状态$STATE ...'
            ;;
        20) # 第二个阶段开始
            # 如果上一次还是从这里退出,可以省略重复的操作
            if [ $LASTSTATE == $STATE ]; then
                continue
            fi
            echo '状态$STATE ...'
            ;;
        21# 若干操作
            res=go
            if [ $res == 'yes' ]; then
                # 进行阶段内的步骤的切换
                STATE=29
                continue
            fi
            ;;
        29) # 第二个阶段的阶段末工作
            echo '状态$STATE ...'
            ;;
        30) # 第三阶段,整个过程的收尾阶段
            echo '状态$STATE ...'
            break
            ;;
        *) # 其他的错误退出状态
            error '错误退出 ...'
            exit 1
            ;;
    esac
    LASTSTATE=$STATE

    if go; then
    # 如果交互的结果是下一步,则状态增1,进入下一步
        STATE=$(($STATE + 1))
    else
    # 如果交互的结果是回到上一步
    # 分两种情况
    # 一种是在整十的状态(整十的状态表示阶段的开始)下选择回退,则直接退回上一个阶段的开始(上一个整十),即SATTE-10
    # 另一种情况是非整十的状态下选择回退,则退回上一步即可,即STATE-1
        STATELEVEL=$(($STATE / 10 * 10))
        if [ $STATE -eq $STATELEVEL ]; then
            STATE=$((STATE -10))
        else
            STATE=$(($STATE -1))
        fi
    fi
done
exit 0  
  1. 关于其中的交互函数,在debian软件包开发中,我一般就用debconf了,调用db_input等函数实现字符界面的交互。而且注意交互的时候是只有两个选择:上一步或下一步
  2. 这个示例来自一个叫localechooser的debian软件包,是一种udeb格式的软件包。源码下载,可以直接下载,或是先配上deb-src的软件源,然后# apt-get source localechooser来下载其源码包,其中有一个叫localechooser的bash脚本,以上示例就摘自其中。

猜你喜欢

转载自blog.csdn.net/u013390088/article/details/82223770
今日推荐