Project with somewhat simple bourne shell cript..

Right now if I have a file that has the following information (with : as the delimiter)

name :address :phone number

I need to be able to do the following commands:
-n search for a name
-p search for a phone number
-l search for a last name starting with a particular
-c find an area code
-a add a new record to the file
-r replace an entry with new data

An example of running the script would be :

perl ./phonebook -l A (-l is first arguement and A is second arguement)
perl ./phonebook -a Jones, Edward

I currently have:

#if there are no arguements (IE -r, -l, ect) than output the file
if [ $# -eq 0 ]
then
cat < dirInfo

#if the first arguement is -n, output any line that contains the 2nd argument (this WORKS, and if the name is the 2nd argument it will output the whole line of information)
elif [ "$1" = "-n" ]
then
grep $2 dirInfo

#I keep getting a "syntax error near unexpected token `('" error.  I figured I could use the grep for the phone number just like the name?  
#I have also tried something like grep '[0-9]\{3\}-[0-9]\{4\}'	but dont know how to compare with 2nd arguement.
elif [ "$1" == "-p" ]
then
grep $2 dirInfo

#I cant grep a variable? This seems to be one of the main things stopping me, I dont know how to incorporate the variable (their input) into grep.
elif [ "$1" == "-l" ]
then
grep '^$2' dirInfo

#As for finding an area code, I would assume thats very similar to finding the whole number, with a small edit of the code.
elif [ "$1" == "-c" ]
then

#Appending a name that they enter (arguement 2).  This does not work at all.
elif [ "$1" == "-a" ]
then
sed '$a\$2'

#=: command not found
elif [ "$1" == "-r" ]
then
echo "Enter the new name: "
read name
echo "Enter the new address: "
read address
echo "Enter the new phone number: "
read phonenumber
$line = grep $2 dirInfo
sed 's/$line/name, address, phonenumber/p' dirInfo
else
echo "not found."
fi

I know there are tons of problems :frowning: I have been googling and reading "Unix The Ultimate Guide by Sumitabha Das" but am still in need of a lot of help. Any input is appreciated, thanks!

You need to quote your arguments (and check how you spell "argument", wink wink) -- that should solve several of your problems.

grep "$2" dirInfo

Single quotes will prevent the expansion of $2 into its value; you are then grepping literally for (end of line) 2 which will never match. (Remember $ means end of line in regular expressions.) So don't use single quotes around a variable.

Things get tricky when you want to use both single quotes and double quotes, but you can even mix them in the same string. So to grep for $2 at end of line you could do something like

grep "$2"'$' file

That's $2 in double quotes, and $ in single quotes, without any space or anything in between. (Next week, we will look at double quotes in single quotes and single quotes in double quotes in the same string.)

What's with the perl? This is a shell script, you'd run it with sh, not perl (although I guess perl is always Doing What You Mean and will actually run sh for you if it sees that you are giving it a shell script; but that sounds rather fragile for you to rely on).

Thank you so much for your reply. Sorry about the spelling!

To check the last name (input is the first letter) this worked!:
grep '^'"$2" dirInfo

One of my biggest questions is why the grep wont work for a string such as (123)456-7899. I get the syntax error near unexpected token `(' error.

-r
-c
-p

these are my only current problems. Two of them are with the area code/phone number so if I can figure out one than the other should be somewhat simple. I will continue to work on it but if anyone has any suggestions I would greatly appreciate them, thanks.

I'm guessing the syntax error is due to quoting issues also. Did you try adding double quotes around $2 everywhere?

yes i believe so.

#Doesnt Work
elif [ "$1" == "-p" ]
then
grep "$2" dirInfo

-bash-2.05b$ ./phonebook -p (324)343-3421
-bash: syntax error near unexpected token `('

It seems as though its treating this phone number differently than a name?

it is Bash (your shell), not your script, that is complaining about the brackets. try

./phonebook -p "(324)343-3421"

bash will parse the command line before it sends it to the script. To bash any expression in () is to be run in a sub-shell.

WOW thank you so much! Is there any way to edit it in my code so I dont have to put the quotation marks in the input?

Nope. I would suggest you change the input format so it doesn't require the parentheses.

elif [ "$1" == "-r" ]
then
echo "Enter the new name: "
read name
echo "Enter the new address: "
read address
echo "Enter the new phone number: "
read phonenumber
#ERROR line = 'grep $2 dirInfo'
sed -e 's/$line/$name $address $phonenumber/g' dirInfo
else
echo "not found."

Still having problems. Can I not assign grep output to a variable?

try putting the grep instruction in backticks not single quotes. or use this form:

line=$(grep $2 dirInfo)

or

line=`grep $2 dirInfo`

thanks very much for the reply

line = $(grep $2 dirInfo) #Gives the error: line: command not found
line = 'grep $2 dirInfo' #Gives the error: line: command not found

Is there a different way to replace the line (if $2 exists) that might be easier?

You can't have spaces around the equals sign. But you might as well inline this into the sed script.

sed "s/.*$2.*/$name $address $phonenumber/" dirInfo

If you want to replace an existing entry in dirInfo, you need to save the result somewhere; this will merely print it. If your sed has the -i option, that's something you could explore.

However, this loses the information about whether the match was successful or not, so you might need to refactor it so that an error message can be printed if not. Maybe your grep idea was better after all.

You might want to anchor the search string a little better; if somebody says they want to replace "a" in the phone book, this will replace all lines containing the letter a anywhere in them.

Thanks for the reply, i really do appreciate all help.

I couldnt get that to work though, as i encountered many different problems

I currently have:

#delete the line that include the name that they enter

sed '$a\'"$name         :$address               :$phonenumber" dirInfo

#sort and output file dirInfo

Basically im adding the users new input, but I still need to delete the original name.

I tried sed '/$2/d' dirInfo but that didnt work, any ideas?

Again, don't use single quotes if you want variables to be expanded; use double quotes.

This will still delete all lines which contain the argument string anywhere in them; perhaps you would be better off if you required the argument to match the entire first field, exactly.

sed "/^$2:/d"

It seems like I have tried every possible thing. :frowning: when I do exactly what you suggested it just acts like a cat (when the user is inputing information, it keeps going until i press ctrl+d). If I can just figure out how to delete the line containing the pattern of $2 (first and last name) than id be fine.

Thanks for any/all help.

could it have anything to do with the quotations that get entered as input?

Do you have both first and last name in "$2", or do you need to put in "$2 $3" (or some variation, maybe "$3, $2"?)

Try temporarily echoing the parameters' values near the beginning of your script so you can see what is getting passed in in $1, $2, etc.

echo "######## \$1 is '$1'"
echo "######## \$2 is '$2'"
echo "######## \$3 is '$3'"

Thanks for the reply, my current code:

elif [ "$1" == "-r" ]
then
echo "Enter the new name: "
read name
echo "Enter the new address: "
read address
echo "Enter the new phone number: "
read phonenumber

#Delete is not working
sed "/^$2:/d"

#Outputs new name and information, then sorts the whole list
sed '$a\'"$name         :$address               :$phonenumber" dirInfo | sort

else
echo "not found."
fi

To run the program: ./phonebook -r "Anderson, Thomas"

echo $1 outputs -r
echo $2 outputs Anderson, Thomas

But you are still not saving the output of sed anywhere!

If your sed supports the -i option, that's convenient. Otherwise, something like

(sed -e '$a\'"$name :$address :$phonenumber" -e "/^$2:/d" | sort -o dirInfo) <dirInfo

allows you to do it without saving to a temporary file. (Or use a temp file if that looks scary, by all means.)