【问题标题】:Exit from while condition only when job done in bash仅当在 bash 中完成工作时才退出 while 条件
【发布时间】:2021-01-22 00:02:00
【问题描述】:

##对不起我的英语不好

您好,我正在编写一个脚本,要求员工按顺序在选项 3 处添加记录:电话号码、姓氏、名字、部门编号、职位等。 我的问题是,当我输入正确的电话号码时,脚本不会询问我的姓氏或其他任何内容并退出.. 我希望此代码在验证正确的电话号码后询问我的姓氏、名字......开。

代码如下

#!/bin/bash

# Define the menu list here
while :
do
    echo "1 - Print All Current Records"
    echo "2 - Search for Specific Record(s)"
    echo "3 - Add New Records"
    echo "4 – Delete Records"
    echo "Q – Quit"
    echo ""
    read -p "Your selection: " option
# What to do if any of the above is selected.
    case $option in
    1)
    cat records
    ;;
    2)
    read -p "Enter keyword: " keyword
    if grep -i $keyword records >> .rec
    then
        cat .rec
    elif [ -z $keyword ]
    then
        echo "Keyword not entered"
    else
        echo $keyword not found
    fi
    ;;
    3)
    printf "\nAdd New Employee Record"

    while :
    do
        read -p "Phone number (xxxxxxxx): " PhoneNumber
# Validate phone number
        if [ -z "$PhoneNumber" ]
        then
            echo "Phone number not entered"
    
        elif ! [ "$PhoneNumber" -eq "$PhoneNumber" ] 2> /dev/null
        then
            echo "Sorry integers only"
        elif [ ! ${#PhoneNumber} -eq 8 ] || [[ ! ${PhoneNumber:0:1} == "9" ]]
        then
        echo "Invalid Phone number"
        elif grep -q $PhoneNumber records
        then
        echo "Phone number exists"
        else
        echo $PhoneNumber >> records
        fi
    done
    
    while :
    do
        read -p "Family Name: " FamilyName
# Validate Family Name
        if [ -z $FamilyName ] || echo "$FamilyName" | grep -i -q '^[a-z/ ]*$'
        then
        echo $FamilyName >> records
        else
        echo "Family name can contain only alphabetic characters and spaces"
        fi
    done

    while :
    do
        read -p "Given Name: " GivenName
# Validate Given Name
        if [ -z $GivenName ] || echo "$GivenName" | grep -i -q '^[a-z/ ]*$'
            then
            echo $GivenName >> records
            else
            echo "Given name can contain only alphabetic characters and spaces"
            fi
    done

    while :
    do
        read -p "Department Number: " DptNum
# Validate Department Number
        if [ -z $DptNum ] || [ ! ${#DptNum} -eq 2 ] || ! [ "$DptNum" -eq "$DptNum" ] 2> /dev/null
        then
        echo "A valid department number contains 2 digits"
        else
        echo $DptNum >> records
        fi
    done

    while :
    do
        read -p "Job Title: " JobTitle
# Validate Job Title

            if [ -z $JobTitle ] || echo "$JobTitle" | grep -i -q '^[a-z/ ]*$'
            then
            echo $JobTitle >> records
            else
            echo "Job title  can contain only alphabetic characters and spaces"
            fi
    done

    printf "Adding new employee record to the records file ...\nNew record saved.\n"
    while true
    do
        read -p "Add another? (y)es or (n)o: " choice
        case $choice in
        [Yy] ) echo ok; break;;
        [Nn] ) exit;;
        * ) echo "Please press y or n";;
        esac
    done
    ;;

    4)
    echo "Delete Employee Record"; echo /n
    read -p "Enter a Phone number: " fon
# Validate phone number
        if [ -z "$fon" ] || ! [ "$fon" -eq "$fon" ] 2> /dev/null || [ ! ${#fon} -eq 8 ] || [[ ! ${fon:0:1} == "9" ]]
        then
            echo "Invalid Phone Number"
        elif ! grep -q $fon records
        then
            echo "Phone number not found"
        else
            grep $fon records
        fi

    while true
    do
        read -p "Confirm deletion: (y)es or (n)o: " answer
            case $answer in
                [Yy] ) grep -v "$answer" records >tempfile && rm records && mv tempfile records
            echo "Record deleted."; break;;
                [Nn] ) break;;
        [Qq] ) exit 0;;
                * ) echo "Please press y or n or q for exit.";;
            esac
        done

    ;;

    Q)
    break
    ;;
    *)
    echo Invalid selection
    ;;
    esac
done

【问题讨论】:

  • 在寻求人工帮助之前尝试shellcheck.net,并尝试将您的问题减少到minimal reproducible example。完全不清楚代码的哪一部分没有按应有的方式工作,很可能部分或全部问题是由于简单的引用错误造成的,Shellcheck 很乐意指出。另见When to wrap quotes around a shell variable
  • 它是退出,还是一遍又一遍地询问电话号码?
  • @GordonDavisson 对不起我的错误,它一直在问电话号码。

标签: bash loops while-loop


【解决方案1】:

我看到的最简单的解决方案是在每个 while 循环中添加一个计数器。

-- 代码 --

cnt=0
while [ $cnt -lt 1]:
do
  #all-the-code-for-adding-record
  cnt=(( $cnt + 1 ))
done

或者其次,将所有执行语句添加到函数定义中并从主循环中调用它们,

-- 改进--

function my_func() {
  # all-executions
}

function other_func() {
  # other-executions
}

read -p "please-input-option" option
case $option in
1)
  my_func()
;;
2)
  other_func()
;;
echo "invalid case"
esac

【讨论】:

    【解决方案2】:

    问题是电话号码的提示处于没有退出条件的循环中:

    while :
    do
        read -p "Phone number (xxxxxxxx): " PhoneNumber
    # Validate phone number
        if [ -z "$PhoneNumber" ]
        ......
        else
        echo $PhoneNumber >> records
        fi
    done
    

    while : 意味着循环条件永远不会为假,这意味着只有在其中运行break(或类似的东西)时循环才会退出。我想你想在echo之后添加break,所以在成功记录电话号码后循环退出。在许多其他循环中,您基本上遇到了同样的问题。

    删除部分还有一个相反的问题:它检查给定的电话号码是否有效且存在,但不管它是否有效都进入“确认删除”循环。

    此外,它看起来不是通过将所有新员工的信息写入一行来创建新条目,而是将每条信息写入单独的行。我认为您想累积有关新员工的所有信息,然后使用单个 echo(或 printf 可能更好——但正确使用更复杂)将员工的信息写成一行。

    我还建议用正则表达式测试替换大多数/所有格式检查。例如,您可以替换:

    if [ -z "$fon" ] || ! [ "$fon" -eq "$fon" ] 2> /dev/null || [ ! ${#fon} -eq 8 ] || [[ ! ${fon:0:1} == "9" ]]
    

    phoneformat='^9[0-9]{8}$'    # Regex for a "9" followed by 8 more digits
    if [[ "$fon" =~ $phoneformat ]]
    

    最后,有很多地方没有正确引用变量引用。我推荐shellcheck.net 指出这个和其他常见错误。

    【讨论】:

      猜你喜欢
      • 2012-04-28
      • 2023-01-12
      • 2016-03-09
      • 2020-03-22
      • 2016-07-27
      • 1970-01-01
      • 1970-01-01
      • 2017-10-16
      • 2019-09-20
      相关资源
      最近更新 更多