【问题标题】:Grep statement in If-Then-Else Statment is not giving intended resultsIf-Then-Else Statment 中的 Grep 语句未给出预期结果
【发布时间】:2015-03-06 04:09:45
【问题描述】:

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

在大多数情况下,我已经完全弄清楚了这段代码。但是,我遇到了给我带来很多麻烦的错误。

代码如下:

#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: $c1\nFirst Name: $c2\nSTUDENT 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 语句搜索了几个小时,但无法弄清楚。

另外:在旁注中,有人知道如何制作它,因此我可以在直到...Do 语句中输入“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: $last\nFirst Name: $first\nSTUDENT 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 命令吗?

【问题讨论】:

  • 你用什么命令来执行这个程序?
  • 这只是程序的一部分,这个循环位于 case 语句中,该语句具有添加记录、搜索记录和修改记录等其他选项。当我执行程序时,它在一个必须命令行参数的 Unix 系统上。例如,它看起来像“asg7s ash7f1 HOLD_FILE”。
  • asg7s是可执行文件
  • 我认为@Samik 试图询问您是否正确使用bash,或者您是否使用sh 执行它,这是行不通的。
  • 抱歉,我必须使用 ksh 或 korn shell

标签: unix grep ksh


【解决方案1】:

您使用了&lt;&lt;&lt;,这是一个仅限 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: $1\nFirst Name: $2\nI 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 作为姓氏怎么办?修改后的代码只会删除一个用户,不管输入多短;但也许grep 也应该被锚定以使用更严格的搜索表达式。

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

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

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

【讨论】:

  • 谢谢您,看来可以了,我会在早上输入并回复您。感谢您的帮助。我想知道为什么它只是打印结果。
  • 当然,对于任何类似于现实世界的用途,您可以使用实际的数据库来处理类似的事情。
  • case 语句中的break 后面应该是两个分号。你似乎抄错了代码。
  • 您还需要在大写的喊话消息中将c1c2 替换为$1$2
  • 好的,我现在明白了,我有点担心这些可能会被用作我最初的第一个和第二个命令行参数,但我会尝试一下并回复你
猜你喜欢
  • 2013-06-18
  • 2021-09-23
  • 2014-10-28
  • 2013-05-29
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-11
相关资源
最近更新 更多