循环进入菜单,直到选择条件或退出/退出选项

时间:2018-09-15 15:46:32

标签: bash

我正在编写一个bash脚本,用户可以在其中添加新数据库。

脚本需要检查用户输入的名称是否有效,以及是否已经存在具有相同名称的数据库。

为此,我已经创建了2个函数。

  • is_valid_name,如果有效则返回0,如果无效则返回1
  • is_database,如果存在一个由用户介绍的名称的数据库,则返回0;否则,则返回

在名称无效或数据库已存在的情况下,我想为用户提供添加其他名称或取消/退出的可能性。

我想使用带有两个选项的Menu来做到这一点:

  1. 添加新数据库
  2. 退出

伪代码:

-> A:

echo Add a database
read -r $database   # get the database name from the user
check the entered name - `is_valid_name'

分支1。

  • 如果名称无效,is_valid_name将显示错误并返回1 -> B:
  • 显示带有两个选项的菜单
  • 如果用户选择选项1(添加新数据库),请返回到 A (见上文黑体字)
  • 如果用户选择选项2(退出)存在脚本

第2分行

  • 如果名称有效,请检查数据库是否存在,is_database

    2.1版

    • 如果数据库存在,则显示带有两个选项的菜单,请返回到 B (见上文黑体字)

    2.2版

    • 如果数据库不存在,请继续执行其他代码,例如创建数据库,填充数据库等

我正在考虑使用while do loop来检查数据库的名称和是否都存在,并且如果两者都可以并继续执行代码或者用户想要存在,则退出循环。

我不知道如何设置(不作为语法)循环来捕获这两个条件

2 个答案:

答案 0 :(得分:2)

如果我正确理解,将可以完成以下任务:

#!/usr/bin/env bash

function is_entity()
{
    # fill in to do what you want
    printf "%s\n" "$1"
}

while true
do
    echo Add New Entity:
    read -r entity
    if is_entity "$entity"; then
    select TASK in 'Entity exist, use another name' 'Logout'
    do
        case "$REPLY" in
        1)
            continue 2
            ;;
        2)
            printf "Bye\n"
            exit 0
            ;;
        esac
    done
    fi
done

答案 1 :(得分:1)

首先,请勿使用全大写的变量名,这些变量名通常保留供系统使用。 (不是您不能,这只是错误的形式)。为用户变量使用小写的变量名。

虽然还不能100%地了解脚本的其余部分应该做什么,但是看起来您似乎正在尝试使用is_entity()来构建没有重复项的列表,以检查'entity'是否已经存在,并且如果返回0,否则返回1。这部分很清楚-尚不清楚的是,如何在其余脚本中对如何使用它的解释有所帮助。

让我们以这种方式来看待它,以检查是否存在一个实体,该实体必须在某处存在它们的集合。对于bash来说,将它们排列成阵列是有意义的。因此,要检查数组中是否存在实体,可以执行以下操作:

declare -a entity   # declare an empty indexed array to hold entities
logout=0            # a flag to handle your 'logout' entry

## check if first argument in entity array
#  return 0 if it exists, 1 otherwise
is_entity() {

    for i in "${entity[@]}"             # loop over array comparing entries
    do
        [ "$i" = "$1" ] && return 0     # if found, return 0
    done

    return 1    # otherwise return 1
}

该函数提供了一个简单的功能,用于检查给定函数的第一个参数时entity数组中是否存在上一个元素(如果没有给出任何参数,则会进行错误处理)

如果要有一组实体,则需要一种添加它们的方法。第二个简单的add_entity()函数可以调用您的is_entity()函数,如果选择的名称已经在数组中,则可以调用return 0;否则,只需将新名称添加到数组并显示一个稍有不同的菜单,使您知道该实体是“已添加”而不是“存在”。像下面这样的简单事情将起作用:

## add entity to array
#  return 0 if it exists, 1 otherwise
add_entity () {
    local name

    printf "\nenter name: "     # prompt for new entity name
    read name

    is_entity "$name"           # check if it exists with is_entity
    if [ $? -eq '0' ]
    then
        return 0                # if so, return 0
    else
        entity+=( "$name" )     # otherwise add it to array
    fi

    return 1                    # and return 1
}

注意:,使用local作为名称来确保name变量仅限于函数范围,并且在函数返回时未设置)

您可以使用两个case语句来实现脚本的其余部分,以显示“添加的”菜单或“存在的”菜单以及两个选择来添加另一个(或选择另一个名称)。 add_entity()的回报。本质上,您将连续循环直到选择了logout,然后在循环开始时调用add_entity(),然后根据返回值使用case语句来确定要显示的菜单。逻辑概要如下:

while [ "$logout" -eq '0' ]   ## main loop -- loop until logout -ne 0
do
    add_entity      # prompt and check with add_entity/is_entity
    case "$?" in    # filter return with case
        0   )       # if the entered name already existed
        ## Existed Menu
        1   )       # if the entity did not exist, but was added to array
        ## Added Menu
    esac
done

在每种情况下,“现有”或“添加”菜单都可以使用简单的select循环,并且对于您"Exists"而言,可能类似于以下内容:

            printf "\nEntity exists - '%s'\n" "${entity[$((${#entity[@]}-1))]}"
            select task in "use another name" "logout"  # display exists menu
            do
                case "$task" in
                "use another name"   )  # select menu matches string
                    break
                    ;;
                "logout"   )
                    logout=1  # set logout flag to break outer loop
                    break;
                    ;;
                ""  )   # warn on invalid input
                    printf "invalid choice\n" >&2
                    ;;
                esac
            done
            ;;

要验证操作以及是否已收集您的实体,您可以在退出循环后简单地显示数组的内容,例如

printf "\nthe entities in the array are:\n"
for ((i = 0; i < ${#entity[@]}; i++))
do
    printf "  entity[%2d] %s\n" "$i" "${entity[i]}"
done

将难题的所有部分放在一起,您可以处理自己的逻辑并使用类似于以下脚本的脚本显示适当的菜单:

#!/bin/bash

declare -a entity   # declare an empty indexed array to hold entities
logout=0            # a flag to handle your 'logout' entry

## check if first argument in entity array
#  return 0 if it exists, 1 otherwise
is_entity() {

    for i in "${entity[@]}"             # loop over array comparing entries
    do
        [ "$i" = "$1" ] && return 0     # if found, return 0
    done

    return 1    # otherwise return 1
}

## add entity to array
#  return 0 if it exists, 1 otherwise
add_entity () {
    local name

    printf "\nenter name: "     # prompt for new entity name
    read name

    is_entity "$name"           # check if it exists with is_entity
    if [ $? -eq '0' ]
    then
        return 0                # if so, return 0
    else
        entity+=( "$name" )     # otherwise add it to array
    fi

    return 1                    # and return 1
}

while [ "$logout" -eq '0' ]   ## main loop -- loop until logout -ne 0
do
    add_entity      # prompt and check with add_entity/is_entity
    case "$?" in    # filter return with case
        0   )       # if the entered name already existed
            printf "\nEntity exists - '%s'\n" "${entity[$((${#entity[@]}-1))]}"
            select task in "use another name" "logout"  # display exists menu
            do
                case "$task" in
                "use another name"   )  # select menu matches string
                    break
                    ;;
                "logout"   )
                    logout=1  # set logout flag to break outer loop
                    break;
                    ;;
                ""  )   # warn on invalid input
                    printf "invalid choice\n" >&2
                    ;;
                esac
            done
            ;;
        1   )       # if the entity did not exist, but was added to array
            printf "\nEntity added - '%s'\n" "${entity[$((${#entity[@]}-1))]}"
            select task in "Add another" "logout"   # display added menu
            do
                case "$task" in
                "Add another"   )
                    break
                    ;;
                "logout"   )
                    logout=1
                    break
                    ;;
                ""  )
                    printf "invalid choice\n" >&2
                    ;;
                esac
            done
            ;;
    esac
done

printf "\nthe entities in the array are:\n"
for ((i = 0; i < ${#entity[@]}; i++))
do
    printf "  entity[%2d] %s\n" "$i" "${entity[i]}"
done

使用/输出示例

运行脚本以验证菜单并测试脚本对不同输入的响应,您可以执行以下操作:

$ bash ~/tmp/entity_exists.sh

enter name: one

Entity added - 'one'
1) Add another
2) logout
#? 1

enter name: one

Entity exists - 'one'
1) use another name
2) logout
#? crud!
invalid choice
#? 1

enter name: two

Entity added - 'two'
1) Add another
2) logout
#? 1

enter name: three

Entity added - 'three'
1) Add another
2) logout
#? 2

the entities in the array are:
  entity[ 0] one
  entity[ 1] two
  entity[ 2] three

仔细检查一下,如果还有其他问题,请告诉我。仅告诉您如何检查is_entity()而不知道如何存储它们有点困难,但是这里的逻辑可以适应多种不同的情况。

相关问题