问题
The intended result of this program is to perform the deletion of a record from a temporary file by searching for the last name. If the name is in the file it will display a message that the record is deleted from the file. The message will have a last and first name of the person deleted. If there is no record for the name entered, display an error message indicating that the name is not in the file. The error message will have the last name of the person searched.
For the most part I have figured this code completely out. However, I am running into errors that are giving me a lot of trouble.
Code is as follows:
#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
;;
So what happens when I execute this code is it brings up the delete message and asks me to input a last name. I put in a last name "smith", when I do this it skips the whole if statement and goes right to the end of the loop and then brings me right up to asking me what the last name is of the person I want to delete. So obviously it is concentrated in the grep statement somewhere. Another odd thing is if I put a name that I know is not in there it will take me to the else statement and give me the error message and ask me if I want to search again.
Any help would be appreciated, I been searching for hours with the grep statement and cannot figure it out.
Additionally: On a side note does anybody know how to make it so I can input "n" or "N" in the Until...Do statement to keep the loop going?
EDIT:
Ok I fixed all the other problems in this code but there is just one problem I cannot fix. Every time I delete an entry from the file it doesn't allow me to execute the echo command.
Code is as follows:
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
;;
As you can see I execute the echo command but it never displays. However, I can tell that it deletes the entry from the file when I exit the program and check it. Does anybody know how to make it display the echo command correctly?
回答1:
You have used <<<
which is a Bash-only feature.
The proper way to debug your problem is to run your script with ksh -x script arg
(or possibly sh -x script arg
if your script was a pure Bourne shell script; but this one isn't).
However, you have some peculiarities in your code. Allow me to offer a refactoring.
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
Another problem here was unrelated to your question. Directly executing the user's input in the regex would be extremely careless -- what if somebody input just a
for a last name? The changed code will only delete one user, regardless of how short the input; but perhaps the grep
should also be anchored to use a tighter search expression.
There is still a possibility that a peculiar name in the database would not match itself, or match more than itself. For example, I use my second given name, so where my full name is required, I often input my name as "First *Middle Last" with an asterisk next to the name I use, which is the convention where I live; but the string *Middle
will not match itself in a regular expression.
Also, without -i
, the sed
script would simply print a copy of the database to standard output.
The delete_choice
variable is not getting updated anywhere within your code so you could change the exterior loop to just while true
and handle exiting by breaking out of the loop, like I have done. I didn't change the until
on the vague speculation that this might be used in other parts of your code which you aren't showing.
来源:https://stackoverflow.com/questions/28892215/grep-statement-in-if-then-else-statment-is-not-giving-intended-results