此程序的预期结果是通过搜索姓氏从临时文件中删除记录。如果该名称在文件中,则会显示一条消息,说明该记录已从文件中删除。该消息将删除个人的姓氏和名字。如果没有输入名称的记录,则显示一条错误消息,指示该名称不在文件中。错误消息将显示被搜索人员的姓氏。
在大多数情况下,我已经完全理解了这段代码。然而,我遇到了一些错误,这些错误给我带来了很多麻烦。
代码如下:
#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在正则表达式中将不与其自身匹配。
此外,如果没有-i
,sed
脚本将简单地将数据库的副本打印到标准输出。
delete_choice
变量在代码中的任何位置都不会更新,因此您可以将外部循环更改为仅while true
,并通过中断循环来处理退出,就像我所做的那样。我没有更改until
,因为我模糊地猜测它可能会用于您没有显示的代码的其他部分。