0

Folks,

I have an array, ex,

declare -a arr=("crm" "hr" "pos")

I need to output error if the passed value doesn't exist in this array

I'm trying this use below snippet but it prints "No match found" for any value

match=0
for i in "${arr[@]}"; do
  if ! [[  $2 == "$i" ]]; then
    match=1
    break
  fi
done
if [[ $match = 1 ]]; then
  echo "No match found"
fi

Any idea how to loop in array and popup error if value doesn't exist ?

Nurhun
  • 475
  • 1
  • 9
  • 21
  • You can negate the following answer: https://stackoverflow.com/questions/3685970/check-if-a-bash-array-contains-a-value – ceving Aug 27 '21 at 11:08
  • @Nurhun : You break your loop as soon as one array element is **not equal** to $2, setting the (poorly named) variable _match_ to 1. Therefore, the only possibility that the loop does **not** execute a `break` and `match` stays 0, is when $2 is equal to all array elements. This can only happen, if the array exists of identical elements (and they are also equal to $2). Since your array contains of 3 **different** elements, `match` can never end up 0. – user1934428 Aug 27 '21 at 11:47
  • Also, please use `$match == 1` rather than `$match = 1`. For even better safety and clarity, get into the habit of putting the unassignable constant on the left of a comparison, and generally always quoting variables unless there's a reason not to - `1 == "$match"` – Paul Hodges Aug 27 '21 at 13:51

4 Answers4

0

There are already answers about your question see check value is in an array, but a fix/idea for your specific approach is something like.

#!/usr/bin/env bash

declare -a arr=("crm" "hr" "pos")

match=0

for i in "${arr[@]}"; do
  if ! [[  $2 == "$i" ]]; then
    ((match++))
  fi
done

if (( match == ${#arr[*]} )); then
  printf >&2 "No match found\n"
fi

The above script increments match every time the test inside the for loop is true, and in the end compare match with the length of the array ${#arr[*]}. A more verbose output is to put set -x on after the shebang and add a $ sign to the variable match (which is not required) inside the (( )).

if (( $match == ${#arr[*]} )); then

Your original approach always breaks the loop when it does not have a match, doing so will not continue the loop.

Jetchisel
  • 7,493
  • 2
  • 19
  • 18
0

You reversed the logic. Just leave out the ! and swap the final test:

match=0
for i in "${arr[@]}"; do
  if [[  $2 == "$i" ]]; then
    match=1
    break
  fi
done
if [[ $match = 0 ]]; then
  echo "No match found"
fi
jhnc
  • 11,310
  • 1
  • 9
  • 26
0

This doesn't require a loop.
c.f. if a 2 strings BOTH present in 1 array in a bash script

$: x=bar
$: [[ " ${arr[*]} " =~ " $x " ]] && echo found || echo nope
nope
$: x=hr
$: [[ " ${arr[*]} " =~ " $x " ]] && echo found || echo nope
found

or

$: match=0
$: set -- foo bar
$: [[ " ${arr[*]} " =~ " $2 " ]] && match=1 
$: echo match
0
$: set -- foo crm
$: [[ " ${arr[*]} " =~ " $2 " ]] && match=1 
$: echo match
1 
Paul Hodges
  • 13,382
  • 1
  • 17
  • 36
-1

The logic seems incorrect.

If it does not match, you break the loop.

If it does match, the loop goes to the next iteration. Then it becomes unmatched and finally breaks the loop

declare -a arr=("crm" "hr" "pos")
not_match=0
for i in "${arr[@]}"; do
  if  [ "$2" = "$i" ]; then
    not_match=1
    break
  fi
done
if [ $not_match -eq 0 ]; then
  echo "No match found"
fi
nhatnq
  • 1,173
  • 7
  • 16