#!/bin/bash
while echo -n \"Player\'s name?\"
read name
[ $name != \'ZZZ\' ]
do
searchresult=$(grep [$name] playername)
if [ $searchresult = 0 ]
the
grep returns multiple words so shell interprets the if statement as having so many tokens. If you just want to check if there was a match, do this:
if grep "$name" playername &> /dev/null; then
# ....
Quote the variable name:
"$searchresult"
Also, youa have other failures in the script.
It would REALLY HELP if you include a sample of the data in the three files you're using 'grep' on!
You've misunderstood what the
variable=$(command)
operation does. The '$()' operation assigns the standard output of the command to the variable, not the exit code of the command. If you want to use your original script, with the exit code, try this instead:
grep [$name] playername > /dev/null 2>&1
searchresult=$?
The '=' operator in 'test' (also known as '[ ]') is for strings. You really want to use the '-eq' operator instead, which is for integers.
Without the data, I can't really figure out what the rest of the script should look like. As it is, it really looks strange to me.
Since you're using bash, I can make a suggestion for improving your input checking.
target=UnSeT
while [ $target = "UnSeT" ]
do
read -p "if See target (T/t) or team name (M/m)?" target
case "$target" in
[Tt]) target="T";;
[Mm]) target="M";;
*) target="UnSeT"; echo "Please enter T or M.";;
esac
done
Use -eq instead = in your if statement in your script or use -z option to check empty string.
There are multiple things wrong with your script. The most egregious problem is that you need to quote your variables.
For example, if $name
contained a value with a space, you get weird results:
name='a value'
grep [$name] file
would end up grepping for [a
(which isn't a valid regex) in value]
(which almost certainly doesn't exist).
Quoting fixes that, but the use of [...]
in grep
is also weird. For example,
name='abc'
grep "[$name]" file
will find in file
any line which contains a
anywhere in it, or b
anywhere in it, or c
anywhere in it. This can hardly be what you want.
If your intention is to search for a literal string,
grep -F "$name" file
does that.
Here is an attempt to rewrite your script more idiomatically.
#!/bin/sh
while true; do
read -p "Player's name? " name
case $name in "ZZZ" | "") break ;; esac
if grep -F -q "$name" playername; then
# Not sure what the logic should be here?
while true; do
read -p "See target (T/t) or team name (M/m)? " choice
case $choice in
[Tt]) file=targetselected; break ;;
[Mm]) file=teamselected; break ;;
esac
echo "Only enter T/t or M/m. Try again."
done
grep -F "$name" "$file"
else
echo 'no such player'
fi
done
There is nothing Bash-specific in this script, so I changed the shebang line to /bin/sh
.
However, the logic seems awkward. I am imagining your players file would look something like this:
Maisy
Tallulah
Cyril
Eddie
and the teams something like
Tallulah,Chickens,Astronauts
Maisy,Obnoxity,Fallacious
Cyril,Rodents
Eddie,Dirt,False,Breakfast of Champions
then if you search for "all" you would find "Tallulah" in the first file, but print both Maisy and Tallulah from the teams file because they both contain the text "all" somewhere on the line. It would be better to simply search the team or target file directly, perhaps using Awk instead of grep
:
awk -F, -v q="$1" '$1 ~ q' "$file"
and if there was no output, the player didn't exist in the first place.
As you grow more familiar with the Unix shell, you will want to avoid tools which force an interactive dialog. Instead, you might want to have a simple tool like this:
#!/bin/sh
file=players
while true; do
case $1 in
-[Tt]) shift; file=targetselected;;
-[Mm]) shift; file=teamselected;;
*) break;;
esac
done
awk -F, -v q="$1" '$1 ~ q' "$file"
which is easy to use as a component in a larger script, easy to recall from your command history, easy to add not one but many different GUIs around if you really need one, and (once you get used to it) easy to use.