One problem with UNIX: it's not terribly good at "excluding" things.
There's no option to rm that says, "Do what you will with
everything else, but please don't delete these files."
You can sometimes create a complex
wildcard expression (1.16)
that does what you want - but sometimes that's a lot of
work, or maybe even impossible.

Here's one place where UNIX's
command substitution (9.16)
operators
(backquotes) come to the rescue. You can use use ls to list all
the files, pipe the output into a
grep -v or egrep -v (27.3)
command,
and then
use backquotes to give the resulting list to rm.
Here's what this command would look like:

% rm -i `ls -d *.txt | grep -v '^john\.txt$'`

[Actually, when you're matching just one filename,
fgrep -v -x (27.6)
might be better. -JP ]
This command deletes all files whose names end in .txt, except
for john.txt. I've probably been more careful than you need to
be about making sure there aren't any extraneous matches; in most
cases, grep -v john would probably suffice.
Using
ls -d (16.8)
makes sure that ls doesn't look into any
subdirectories and give you those filenames.
The
rm -i (21.11)
asks you before removing each file; if you're
sure of yourself, omit the -i.

Of course, if you want to exclude two files, you can do that with
egrep:

% rm `ls -d *.txt | egrep -v 'john|mary'`

(Not all egrep implementations support the -v option.
Don't forget to quote the vertical bar (|), to prevent the shell from piping
egrep's output to mary.)