If Then Else Statment中的Grep语句并没有给出预期的结果



此程序的预期结果是通过搜索姓氏从临时文件中删除记录。如果该名称在文件中,则会显示一条消息,说明该记录已从文件中删除。该消息将删除个人的姓氏和名字。如果没有输入名称的记录,则显示一条错误消息,指示该名称不在文件中。错误消息将显示被搜索人员的姓氏。

在大多数情况下,我已经完全理解了这段代码。然而,我遇到了一些错误,这些错误给我带来了很多麻烦。

代码如下:

#While loop
            delete_choice="y"           
            until [[ $delete_choice == "n" ]]
            do
            #Create Delete Message
            clear
            echo "                                 Delete Record                                 "
            echo -en 'n'
            echo -en 'n'
            echo "What is the last name of the person you want to delete:"
            read last_name
            if line=$( grep -Fi "$last_name" "$2")
            then
            IFS=: read c1 c2 rest <<< "$line"
            echo -e "Last Name: $c1nFirst Name: $c2nSTUDENT RECORD HAS BEEN DELETED FROM FILE"
            sed "/$line/d" $2
            else
            echo "ERROR: $last_name is not in database"
            echo "Would you like to search again (y/n)"
            read delete_choice
            fi
            done
        ;;

因此,当我执行这段代码时,它会显示删除消息,并要求我输入姓氏。我输入了一个姓氏"smith",当我这样做时,它会跳过整个if语句,直接进入循环的末尾,然后直接问我要删除的人的姓氏是什么。很明显,它集中在grep语句的某个地方。另一件奇怪的事情是,如果我放了一个我知道不在其中的名字,它会把我带到else语句,给我错误消息,并问我是否想再次搜索。

如果有任何帮助,我们将不胜感激,我已经用grep语句搜索了几个小时,但无法弄清楚。

另外:顺便说一句,有人知道如何制作它吗?这样我就可以在Until…中输入"n"或"n"。。。做语句来保持循环?

编辑:

好的,我修复了这段代码中的所有其他问题,但只有一个问题我无法修复。每次我从文件中删除一个条目时,它都不允许我执行echo命令。

代码如下:

d|D)
            #While loop
            delete_choice="y"       
            while true
            do
                #Create Delete Message
                clear
                echo "                                 Delete Record                                 "
                echo -en 'n'
                echo -en 'n'
                echo "What is the last name of the person you want to delete:"
                read last_name
                if line=$(grep -i "^${last_name}:" "$2")
                then
                    echo "$line" |
                    while IFS=: read c1 c2 rest; do
                        last=$c1
                        first=$c2
                        sed -i "/^$c1:$c2:/d" "$2"
                    done
                    echo -e "Last Name: $lastnFirst Name: $firstnSTUDENT RECORD HAS BEEN DELETED FROM FILE"
                else
                    echo "ERROR: $last_name is not in database"
                    echo "Would you like to search again (y/n):"
                    read delete_choice
                    case $delete_choice in [Nn]) break;; esac
                fi
            done
        ;;

正如您所看到的,我执行echo命令,但它从不显示。然而,当我退出程序并检查它时,我可以看出它会删除文件中的条目。有人知道如何使它正确显示echo命令吗?

您已经使用了<<<,这是一个仅限Bash的功能。

调试问题的正确方法是使用ksh -x script arg运行脚本(如果脚本是纯Bourne shell脚本,则可能使用sh -x script arg;但此脚本不是)。

但是,您的代码中有一些特性。请允许我提供一个重构。

delete_choice="y"           
until [[ "$delete_choice" == "n" ]]
do           # Indent your control structures
    clear
    echo "                                 Delete Record"
    echo # Massive trailing whitespace removed ----------^^^
    echo # Just echo to output a new line
    echo "What is the last name of the person you want to delete:"
    read last_name
    case $last_name in [Nn]) break;; esac      # Exit on "n"
    if line=$(grep -Fi "$last_name" "$2")
    then     # Indent your control structures
        file=$2
        oldIFS=$IFS
        IFS=:
        set -- "$line"   # break input into $1, $2, etc
        IFS=$oldIFS
        echo -e "Last Name: $1nFirst Name: $2nI SCREAM IN UPPER CASE"
        sed -i "/^$1:$2:/d" "$file"   # note quoting and -i and changed variable
    else
        echo "ERROR: $last_name is not in database"
        echo "Would you like to search again (y/n)"
        read delete_choice
    fi
done

这里的另一个问题与你的问题无关。直接在正则表达式中执行用户的输入是非常粗心的——如果有人只输入姓氏的a呢?更改后的代码将只删除一个用户,而不管输入有多短;但也许CCD_ 5也应该被锚定以使用更严格的搜索表达式。

数据库中的特殊名称仍有可能与自身不匹配,或者与自身不太匹配。例如,我使用我的第二个名字,所以在需要我的全名的地方,我经常将我的名字输入为"First*Middle Last",在我使用的名字旁边加一个星号,这是我居住的地方的惯例;但是字符串CCD_ 6在正则表达式中将不与其自身匹配。

此外,如果没有-ised脚本将简单地将数据库的副本打印到标准输出。

delete_choice变量在代码中的任何位置都不会更新,因此您可以将外部循环更改为仅while true,并通过中断循环来处理退出,就像我所做的那样。我没有更改until,因为我模糊地猜测它可能会用于您没有显示的代码的其他部分。

相关内容

最新更新