LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 10-11-2008, 04:50 PM   #1
cybergeek11235
LQ Newbie
 
Registered: Oct 2008
Posts: 2

Rep: Reputation: 0
bash scripting question, homework related


Hey gang - short time lurker, first time poster.

So, in my Linux+ pre-cert course, we've got an assignment to make an address book script. It's supposed to be able to let users add, search, and view all entries. Entries are to be saved in a plaintext file with a custom field delimiter (which should, naturally, not show itself when the user is finding listings), and should have such fields as 'name', 'address', 'phone number', and 'email'. We can get extra credit for going above and beyond, which leads me to the reason for posting:

I'm trying to add in the ability to delete entries. I've got it working to the degree that if it can find one-and-only-one entry with data that contains the search string, it'll wipe it out, and if it's got more than one possibility, it shows them but doesn't delete any.

I'd like, if possible, to add something that'll let me go through matching entries one by one, and confirm that yes, the user DOES want to delete that particular entry before doing so. It's just occurred to me as I type this out that it probably won't matter how many matches exist for the function's sake, I just need help formulating the loop, and going line-by-line through the matches.

When the entries are stored, they're stored with the caret ("^") as the delimiter. Each entry is its own line in a file called 'address.book' - one such line might look like this: "John Doe^123 Main St^555-1234^jdoe@server.com". Reading-in has so far been handled by an awk loop so as to drop the carets.

Wow, that was longer than I thought it'd be.

I'm happy to post code snippets if it'd be helpful.

Thanks in advance!
 
Old 10-12-2008, 03:04 AM   #2
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
Quote:
Originally Posted by cybergeek11235 View Post
Hey gang - short time lurker, first time poster.
Hello and welcome to LQ. I hope you like it here and I hope you stay on longer than it takes for you to fix your problems. It's nice to see you be upfront about this being homework, but that's not what we're interested in. We'd rather not know since the LQ Rules say you shouldn't expect help with it.

What we're interested in, no, what we need to work with is
Quote:
Originally Posted by cybergeek11235 View Post
I'm happy to post code snippets if it'd be helpful.
yes, code. Posting your code shows us your skill level (which makes it easier to give directions) or point to corrections. So please do.
 
Old 10-12-2008, 10:43 AM   #3
LinuxCrayon
Member
 
Registered: Nov 2007
Location: Georgia, USA
Distribution: FreeBSD
Posts: 274

Rep: Reputation: 31
Quote:
Originally Posted by cybergeek11235 View Post
I'd like, if possible, to add something that'll let me go through matching entries one by one, and confirm that yes, the user DOES want to delete that particular entry before doing so. It's just occurred to me as I type this out that it probably won't matter how many matches exist for the function's sake, I just need help formulating the loop, and going line-by-line through the matches.
Sounds like a FOR loop would work. Have you thought about or tried this?
 
Old 10-12-2008, 06:50 PM   #4
lumak
Member
 
Registered: Aug 2008
Location: Phoenix
Distribution: Arch
Posts: 799
Blog Entries: 32

Rep: Reputation: 111Reputation: 111
I would create a function that continually loops until valid data is entered. The delete option should always print out a menu with the following. Then loop until the user chooses one.

e.g.

All Entries containing 'Smith'

1) Smith, John - address, phone
2) Smith, Jane - address, phone
3) Joe, Smith - address, phone
4) Doe, John - 169 Smith Ln., phone

C) cancel

Which entry would you like to delete?

Code:
function name () {

# all arguments passed to the function
arguments=$*

for #some always true till terminate
do

#print menu

read userchoice

#check
#terminate if valid choice
done
}

I'm sure you have the training to figure out the rest...

Last edited by lumak; 10-12-2008 at 06:52 PM.
 
Old 10-12-2008, 10:59 PM   #5
cybergeek11235
LQ Newbie
 
Registered: Oct 2008
Posts: 2

Original Poster
Rep: Reputation: 0
Hey, thanks for all the help gang! I apologize for the homework thing; I must have skimmed that part a little too quickly. In my defense, I was trying to be as specific-to-the-exact-issue-at-hand as possible, so as to not let any assistance I might get spread outside that sphere of influence.

Try saying *that* three times fast!

Anyhoo, I did some googling and, in conjunction with your ideas, got a while-read loop going that works - mostly.

Here's some internal information that should be helpful, before I get to the actual issue/s - some of this was in my initial post, but this way we don't need to worry about scrolling and the like :

When the user stores an entry, the 4 fields (Name (might change to first and last names later, but who knows), Address, Phone Number, and Email) are appended to a straight text file called address.book with carets ("^") as delimiters. So, for example, you might see something like:

John Doe^123 Main St^555-1234^jdoe@server.com

if you were to cat the address.book file. When the file is searched, as I'm sure you guys could guess, no reformatting is necessary 'cos grep will either find a match or not regardless of formatting. When an entry is printed, I've got an awk statement to print each line out and to filter out the carets and add newlines in their steads.

I've been working, as I think I mentioned, on a delete function. As I said above, it works for the most part. The only times that it hiccups are:

If there are two identical entries containing letters (e.g. if I throw in the test entry "a^b^c^d", or the full version listed above), it deletes both of them. This is fine; I understand exactly why this happens and I think I've got a way around it that'd involve using the -n flag with grep. Not sure how to implement it just yet, but I'm sure I'll come up with something.

The other time it has issues is if there's two identical entries containing *just* numbers (e.g. "1^2^3^4") in which case it deletes NEITHER of them, but goes through the loop and - as far as I can tell - honestly truly believes that it HAS in fact deleted them.

I have no bloody clue why it's doing this, except maybe to punish me for being too ambitious.

The full delete loop looks like this:

Code:
# Function to delete entries
# Checks to see if the pattern exists in the file. If not, advises user. Else, regardlessof number of hits, cycles through each hit and confirms deletion with user.

deleteEntry() {

   DELETECHECK=0
   FILENAME=address.book

   echo "Please enter some part of the entry you would like to delete (e.g. name, email, etc):"
   read DELETEME
   exec 3<"$FILENAME" #reads address.book through not-stdin so that the user's search pattern can be read with stdin.
   while read -u 3 LINE
   do
        if [ `echo $LINE | grep -i $DELETEME | wc -l` -gt 0 ] #if there's at least 1 instance of the pattern in the line
        then
           echo $LINE | awk -F^ '{print "\n", " ---------- ", "\n", "\n", $1, "\n", $2, "\n", $3, "\n", $4, "\n"}' # print statement used throughout
           echo "Delete this entry? (y/n)"
           read CONFIRM
           if [ $CONFIRM == y -o $CONFIRM == Y ]
           then
                cat address.book | grep -vi "$LINE" > address.book1
                mv address.book1 address.book
           fi
           DELETECHECK=1
        fi
   done

   exec 3<&-

   if [ $DELETECHECK -eq 1 ]
   then
        echo "Deletion occurred. Here is what your address book looks like:"
        awk -F^ '{print "\n", " ---------- ", "\n", "\n", $1, "\n", $2, "\n", $3, "\n", $4}' address.book
   else
        echo "Your search pattern wasn't found in the address book. No changes have been made."
   fi
}
Is there something blindingly obvious that I'm just missing? I'm thinking maybe it's treating the 1/2/3/4 as variables instead of as straight-up text, in which case I should be able to sneak past that with some clever quote-mark usage....right?

Otherwise, if you see anywhere to optimize the code a little more, I'd certainly appreciate the advice! (I'm pretty sure I don't need to put the file name in a variable for the "read the file with not-stdin" part, but I'm not 100% there, and it mostly works as is...)
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
kernel-related homework questions linuxpassion Linux - Newbie 25 03-28-2008 12:04 PM
bash scripting question bmfan Linux - Software 6 11-04-2005 08:54 PM
bash related question Menestrel Linux - Newbie 2 01-25-2005 10:03 AM
Bash scripting question Hammett Linux - General 4 11-29-2004 06:29 AM
bash related question MattSmith Linux - General 1 01-20-2004 05:41 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 11:20 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration