++++++++++++++++++++SNIP HERE+++++++++++++++++++++++++++++++++++++++++ In the "modify item" section, right after the closing bracket for: } # End of until ($counter >= @field_values) is the line: chomp $new_line; # take off last | This line doesn't do what it says it does. As I am given to understand it, the "chomp" function only clips (and returns the number of) newlines at the end of the string. (a) there are no newlines at the end of this string; (b) the code will not remove the "|" character. As a result, the routine appends a | onto the end of every modified item, after the database id number. Now the string for, say, item 20 ends: "...text|20|\n" instead of "...text|20\n" When the search routines in the modify and delete routines look up the item to modify/delete, they split the database fields into an array: @grepfields=split(/\|/,$_); The last item in the array SHOULD be "20\n", BUT since we put in the extra "|" between the 20 (i.e. the db id number) and the newline char, the next- to-last item in @grepfields is "20" and the last item is now "\n" The routine then uses the last array item to compare with the database id of the item to be modified: $database_id = pop (@grepfields); <--$database_id="\n", NOT "20\n" chomp $database_id; <-- $database_id = "", NOT "20" So WE NEVER FIND item 20 as a match. This results in two different errors. (1) In the modify routine, we just write the unmodified entry back out again, AND append the modified pseudoentry to the end of the file as a new entry with a blank database id (2) In the delete routine, we display the item deleted message, but don't actually delete anything. =============================== FIX: Replace the line } # End of until ($counter >= @field_values) chomp $new_line; # take off last | with } # End of until ($counter >= @field_values) # HACK - replace goofy chomp line with chop to specifically remove trailing | while ( $new_line =~ /\|$/ ) { chop ( $new_line ); } # chomp $new_line; # take off last | # ENDHACK