Simple conditional yields too many responses


 
Thread Tools Search this Thread
Top Forums UNIX for Beginners Questions & Answers Simple conditional yields too many responses
# 8  
Old 02-11-2019
Code:
birdnames="duck sparrow hawk"
read -p "Enter name of a bird   " name
if [[ " ${birdnames} " ==  *" ${name// } "* ]]; then
  echo "Yes, that is a bird."
else
  echo "That is not a bird."
fi

--
Or with a bash 4 associative array :

Code:
birdnames=(duck sparrow hawk "horned bill")
declare -A bird
for i in "${birdnames[@]}";
do
  bird[$i]=1
done

read -p "Enter name of a bird   " name
if [[ ${bird[$name]} ]]; then
  echo "Yes, that is a bird."
else
  echo "That is not a bird."
fi

or

Code:
birdnames=(duck sparrow hawk "horned bill")
declare -A bird
for i in "${birdnames[@]}";
do
  bird[$i]=
done

read -p "Enter name of a bird   " name
if [[ ${bird[$name]+1} ]]; then
  echo "Yes, that is a bird."
else
  echo "That is not a bird."
fi

or

Code:
declare -A bird
bird=([duck]= [sparrow]= [hawk]= [horned bill]=)

read -p "Enter name of a bird   " name
if [[ ${bird[$name]+1} ]]; then
  echo "Yes, that is a bird."
else
  echo "That is not a bird."
fi


Last edited by Scrutinizer; 02-11-2019 at 01:49 PM..
This User Gave Thanks to Scrutinizer For This Post:
# 9  
Old 02-11-2019
@rbattel--
Quote:
Can I presume that if you enter hawk then the output you get is:-
Yes, that's exactly what I get. I will work on flag/variable success/failure suggestion.


@joeyg--I'm not sure how to use the Found/NotFound.


@vgersh99--I must have done something wrong. Couldn't get your suggestion to work.


@Scrutinizer--your first code worked exactly as I hoped for. Will get to array and declarations soon.
# 10  
Old 02-11-2019
I suggest you start using real, telling variable names. You may not need it now for your example scripts but once you start writing real, working scripts you will have a hard time telling what all the i's, j's k's and what not are doing. If you search for a bird, call it "bird", not "i".

Furthermore, there is a reason why we almost religiously indent code. Consider the following code:

Code:
if <condition1> ; then
     command1
     if <condition2> ; then
          command2
     else
          command3
     fi
     command4
fi

When is "command1" executed? Answer: if "condition1" is met. When is "command3" executed? Answer: when "condition1" is met AND "condition2" is not met. And so on - the level of indentation tells you when (or: under which conditions) a certain part of the code is executed. In your code:

Code:
for i in $birdname
do
     if [[ "$REPLY" = "$i" ]]; then
             echo "Yes, that is a bird."
     fi
     exit
     if [[ ! "$REPLY" = "$i" ]]; then
         echo "That is not a bird."
      fi
done

When is the "exit" executed? Answer: every time. So, there is your answer why the program does not work the way you expected it. Ask yourself: under which circumstances do i want this command to be executed - and then you know where it is to be placed. We already established further up in the thread that the for-loop iterates through all the birds in your string. So ask yourself what you do want to do if the name is matched and what you want to do if not:

- get first name
- IF it matches, print "this is a bird" and exit
- IF it doesn't match, then what?

Answer: do nothing. Return to the top and get the next name. Hence:

Code:
for bird in "$all_birds" ; do
     if [ "$bird" = "$REPLY" ] ; then
          echo "This is a bird"
          exit
     fi
done

This will say "This is a bird" in case it is - but it will say nothing if it isn't. Now, if something ever matches in this loop, the "exit" command is executed and the loop is aborted. When do we ever get to the end of the loop, hm? We get there only if nothing has matched, so where is the right place to put the negative "isn't a bird" message? Yes, right:

Code:
for bird in "$all_birds" ; do
     if [ "$bird" = "$REPLY" ] ; then
          echo "This is a bird"
          exit
     fi
done
echo "This is not a bird."

Put this into your program and try it.

@joeyg: Your solution is overly complicated and not completely logically sound. First, there is a variable "NOT_FOUND", which you increment but never use. What is the purpose of an unused variable.

Second: once you find a match you carry on till the end of the birds list. This only makes sense if the same bird is mentioned more than once. i.e.

Code:
all_birds="hawk dove hawk pidgeon hawk sparrow"
REPLY="hawk"

AND you want to find out how often it is mentioned in case it is mentioned at all.

If all the birds in the list are distinct this could never happen because every possible content of "$REPLY" can be matched by either one item in the list or by none at all. Therefore you do not need a flag because you can immediately act upon the condition instead of setting a flag and act on that later. You need flags only if you need to "store" the status of a condition and act upon it later. Like, if you want to connect several conditions which you cannot evaluate at once:

Code:
flag1=0
flag2=0
if <condition1> ; then
     flag1=1
fi
if <condition2> ; then
     flag2=1
fi

if (( flag1 + flag2 == 2 )) ; then        # only if both conditions were met (AND)
if (( flag1 + flag2 == 1 )) ; then         # only if exactly one condition was met (exclusive OR)
if (( flag1 + flag2 )) ; then             # if at least one condition was met (OR
if ! (( flag1 + flag2 )) ; then           # if neither of the conditions were met (NOT)

Or, if you need to string different actions on the conditions or their combination:
Code:
flag1=0
flag2=0
if <condition1> ; then
     flag1=1
fi
if <condition2> ; then
     flag2=1
fi

if (( flag1 + flag2 )) ; then
     if (( flag1 + flag2 == 2 )) ; then
          actionA
     fi
     actionB
else
     actionC
fi
if (( flag2 )) ; then
     actionD
fi


I hope this helps.

bakunin
This User Gave Thanks to bakunin For This Post:
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Searching a file - and assigning responses to variables (or something)

So first: Sorry if the title is confusing... I have a script I'm writing with a file with several names in it (some other info - but it's not really pertinent...) - I want to be allow the user to delete certain records, but I ran into a problem I'm not sure how to go about fixing. If I were... (6 Replies)
Discussion started by: sabster
6 Replies

2. UNIX for Dummies Questions & Answers

Cp via NFS vs. scp yields unexpected difference

I have two Linux machines, Linux1 and Linux2. They both have two NFS mounts. We'll call them /scratch1 and /scratch2. And they both reside on the same NetApp filer. If I copy a 512Mb file from /scratch1 to /scratch2 while logged on Linux1 it takes 40s. However if I scp this file from... (1 Reply)
Discussion started by: crimso
1 Replies

3. IP Networking

DNS: Dig returns different responses...

Hey everyone, Okay, so I've been having some fun with the dig command, and wanted to dig my old school. Two questions came up from this. So I: dig @8.8.8.8 +recurse njcu.edu ANY and the result is about 8 records, including the SOA record. One of them is this weird TXT record, and the other is... (1 Reply)
Discussion started by: Lost in Cyberia
1 Replies

4. Infrastructure Monitoring

SNMP responses failing under high system load

Greetings, I've got a Zenoss v2.5 server monitoring a large video encoding farm. Needless to say, these systems are under high bandwidth and CPU utilization the majority of the time. What I'm running into is that, occasionally, these systems will fail to respond to a standard SNMP request,... (1 Reply)
Discussion started by: Karunamon
1 Replies

5. Shell Programming and Scripting

Simple awk conditional one-liner

Hello, I'm looking for an awk one-liner that prints the first two data fields, then contains a conditional where if $3>$4, it prints $3-$4. Otherwise, it prints $3. Example: Data file: 123,456,999,888 333,222,444,555 654,543,345,888 444,777,333,111 Output: 123,456,111 333,222,444... (2 Replies)
Discussion started by: palex
2 Replies

6. Shell Programming and Scripting

Using AWK to Calculate Correct Responses

Hello, I am trying to count how many times a subject makes a correct switch or a correct stay response in a simple task. I have data on which condition they were in (here, labeled "IMAGINE" and "RECALL"), as well as whether they made a left or right button response, and whether the outcome was... (5 Replies)
Discussion started by: Jahn
5 Replies

7. Linux

How do I capture responses from the chat command?

Unfortunately googling the word 'chat' gives you zebedee billion responses that relate to everything and few of them refer to the linux chat command. I've read the man page and found a couple of examples but can't see how to do this. I want to query the modem for it's manufacturer, product id... (8 Replies)
Discussion started by: Bashingaway
8 Replies

8. Shell Programming and Scripting

How to automate responses

I would have searched for this but I couldn't really think of what to use for the search text... I've got a situation where I need to automate responses to an executable when running it from a script so that it can be made into a job the operators don't have to interact with. When I run it... (2 Replies)
Discussion started by: djp
2 Replies

9. UNIX for Dummies Questions & Answers

ping to machine and count responses

if i wanted to ping all the machines in a given directory (/etc/hosts) and return a total count of responses how would i go about scripting that? complete newbie...so be gentle if ; then //$1 = /etc/hosts cd "$1" //this puts me into the directory i need...but how do i send ... (2 Replies)
Discussion started by: trostycp
2 Replies
Login or Register to Ask a Question