You are not logged in.

#1 2015-12-10 12:28:33

xaos52
The Good Doctor
From: Planet of the @pes
Registered: 2015-09-30
Posts: 695

Bash function to test whether an array contains a certain element

has_element () {
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}

To use it in your own scripts, include the function definition and call the function with

if has_element "$needle" "${haystack[@]"; 
then
...
else
...
fi

where you replace 'needle' by the variable containing the element and 'haystack' by the array.

Offline

#2 2015-12-10 19:56:47

gako
Member
Registered: 2015-10-02
Posts: 241

Re: Bash function to test whether an array contains a certain element

This is very useful, thank you xaos52.

Offline

#3 2015-12-11 00:40:05

Horizon_Brave
Operating System: Linux-Nettrix
Registered: 2015-10-18
Posts: 1,473

Re: Bash function to test whether an array contains a certain element

xaos52 wrote:
has_element () {
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}

To use it in your own scripts, include the function definition and call the function with

if has_element "$needle" "${haystack[@]"; 
then
...
else
...
fi

where you replace 'needle' by the variable containing the element and 'haystack' by the array.

Whoo, I'm getting better at this..I can almost completely make sense of this script reading it throught. Xaos my only question is that for the:

 for e in "${@:2}";

Doesn't this expand the array, starting at element 2? Why would you do this and not loop through from the start? Why do you skip the first two elements in the array for?

cheers!


"I have not failed, I have found 10,000 ways that will not work" -Edison

Offline

#4 2015-12-11 02:49:34

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,652
Website

Re: Bash function to test whether an array contains a certain element

That's neat - and a common task - many thanks.

btw Dr xaos, there's also a  "Handy command-line stuff for terminals or scripts" thread for small code scraps that don't necessarily need a whole thread.

Maybe it should be moved I've now moved it from "Off Topic" to "Scripts, Tutorials & Tips".

@Horizon_Brave The first argument of the function is the 'needle', then come the elements of the array.

Last edited by johnraff (2015-12-11 03:05:33)


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#5 2015-12-12 11:42:52

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: Bash function to test whether an array contains a certain element

Thank xaos52, nice solution.

However, something itched me about the 'complexity' of your solution, and I (literally) discovered following works:

# bash script example

# define an array
array=( one two three four )

# just to show that array it zero based (like in C)
echo ${array[0]}

# examples of 'needle' search
# 
echo `expr index "$array" "two"`    # output: 1

echo `expr index "$array" "one"`    # output: 1

echo `expr index "$array" "three"`   # output: 3

echo `expr index "$array" "t"`      # output: 0

echo `expr index "$array" "ten"`    # output: 0

Therefore, the 'expr index' does function as a array values search; it returns a non zero value if needle exists, and zero otherwise.

But, it doesn't returns string position in the array (strange?).

So the test could be:

if [ `expr index "$array" "four"` -eq 0 ]
then
      # do stuff when there is no 'needle' in array
else
      # do stuff when the 'needle' is in array
fi

Funny, I could not find this by googling?!?  8)  cool


Postpone all your duties; if you die, you won't have to do them ..

Offline

#6 2015-12-12 15:42:48

xaos52
The Good Doctor
From: Planet of the @pes
Registered: 2015-09-30
Posts: 695

Re: Bash function to test whether an array contains a certain element

^
NIce try, but this does NOT work reliably!!!
Run this test script to see:

#!/bin/bash
# bash script example
# set -e
# define an array
array=( one two three four )

# just to show that array it zero based (like in C)
# echo ${array[0]}

# examples of 'needle' search
#
for needle in "one" \
                  "two" \
                  "three" \
                  "four" \
                  "ne" \
                  "net" \
                  "netw" \
                  "netwo" \
                  "onetwo" \
                  "onetwothree" \
                  "onetwothreefour" \
                  "hree" \
                  "x" \
                  "A" \
                  "1" \
                  "ef" \
                  "t" \
                  "ten"
do 
    printf -- '--> needle = %s\n' "$needle"
    printf 'output from expr\n'          
    expr index "$array" "$needle"
    rc=$?
    printf 'returned code %d\n' $rc
    if (($rc))
    then
        printf '%s _NOT_ in array\n\n' "$needle"
    else
        printf '%s _IS_ in array\n\n' "$needle"
    fi
done

I am afraid bash can not work miracles:
either you test all elements for needle
or
you build up a string containing all haystack elements, separated by a separator that does not appear in any element and then use
expr index array "<separator>needle<separator>"

I prefer the first method because
(1) you can bail out the moment you found the needle. No need to test remaining elements.
(2) you don't have to build a string with all elaments and separators, which implies reading all array elements.

I'm guessing this is why you did not find this method using google. smile

Offline

#7 2015-12-12 22:58:56

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: Bash function to test whether an array contains a certain element

^You are right ... It doesn't work reliably sad Thanks for taking time to find nice example showing the problem(s).

(I wonder what is going on under the hood in bash with ...)


Postpone all your duties; if you die, you won't have to do them ..

Offline

#8 2015-12-13 01:13:51

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,652
Website

Re: Bash function to test whether an array contains a certain element

btw "$array" only evaluates to the first element ( ${array[0]} ie 'one' ) so this:

expr index "$array" "$needle"

is indexing needle in 'one' only.


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#9 2015-12-13 01:43:26

Horizon_Brave
Operating System: Linux-Nettrix
Registered: 2015-10-18
Posts: 1,473

Re: Bash function to test whether an array contains a certain element

Despite the failed attempt, this opened my eyes to the expr command. I was under the assumption that it could only perform simple mathematics, and string comparison.  I didn't know it could execute functions like index(), match() etc...

My question though is why can't we just run functions from the command line?  If I just enter
index "$array" "two"   

I get a command not found. But if I put the expr command before it, it works. Why is this? Why do functions need the expr (or any other command) to work?  but yet you can run a function in a bash script?


"I have not failed, I have found 10,000 ways that will not work" -Edison

Offline

#10 2015-12-13 01:51:20

johnraff
nullglob
From: Nagoya, Japan
Registered: 2015-09-09
Posts: 12,652
Website

Re: Bash function to test whether an array contains a certain element

^'index' is not a function in this case, it's an argument to the 'expr' command.

You can see all the functions at present available in your shell by typing

set

in a terminal. You might be surprised.


...elevator in the Brain Hotel, broken down but just as well...
( a boring Japan blog (currently paused), now on Bluesky, there's also some GitStuff )

Introduction to the Bunsenlabs Boron Desktop

Offline

#11 2015-12-13 11:11:09

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: Bash function to test whether an array contains a certain element

^^Cannot recommend enough: Advanced Bash-Scripting Guide. In particular: Manipulating strings.

johnraff wrote:

btw "$array" only evaluates to the first element ( ${array[0]} ie 'one' ) so this:

expr index "$array" "$needle"

is indexing needle in 'one' only.

Yes, I'm aware of this. However, it doesn't explain

array=( one two three four )
echo `expr index "$array" "two"`    # output: 1

Actually, I don't quite see the logic behind various output in my (wrong) attempt ... yikes Oh, bash, what are you doing?  big_smile


Postpone all your duties; if you die, you won't have to do them ..

Offline

#12 2015-12-13 16:10:18

xaos52
The Good Doctor
From: Planet of the @pes
Registered: 2015-09-30
Posts: 695

Re: Bash function to test whether an array contains a certain element

After reading the bash info for 'expr index string charset' I now understand why it does not work for our intented purpose:

index STRING CHARSET
     Returns the first position in STRING where the first character in
     CHARSET was found.  If no character in CHARSET is found in STRING,
     return 0.

So

expr index "$array" "two"

means:
find first occurrence of one of the characters 't' 'w' or 'o' in "$array", where "$array" evaluates to "one".
The answer is 1.

Thanks to you posting this, I have learned something new too. smile

Offline

#13 2015-12-13 20:26:09

Horizon_Brave
Operating System: Linux-Nettrix
Registered: 2015-10-18
Posts: 1,473

Re: Bash function to test whether an array contains a certain element

I give you all the most credit for learning and remembering all of this syntax...


"I have not failed, I have found 10,000 ways that will not work" -Edison

Offline

#14 2015-12-14 15:41:34

iMBeCil
WAAAT?
From: Edrychwch o'ch cwmpas
Registered: 2015-09-29
Posts: 767

Re: Bash function to test whether an array contains a certain element

^^Now, xaos51, you made me feel stupid and dumb for not reading carefully enough the bash info  :8  smile


Postpone all your duties; if you die, you won't have to do them ..

Offline

#15 2015-12-14 16:51:48

Horizon_Brave
Operating System: Linux-Nettrix
Registered: 2015-10-18
Posts: 1,473

Re: Bash function to test whether an array contains a certain element

xaos52 wrote:

After reading the bash info for 'expr index string charset' I now understand why it does not work for our intented purpose:

index STRING CHARSET
     Returns the first position in STRING where the first character in
     CHARSET was found.  If no character in CHARSET is found in STRING,
     return 0.

So

expr index "$array" "two"

means:
find first occurrence of one of the characters 't' 'w' or 'o' in "$array", where "$array" evaluates to "one".
The answer is 1.

Thanks to you posting this, I have learned something new too. smile


And the reason for this is because it finds the the 'o' in 'two' to equate to the 'o' in 'one', which is the 1st occurance..Hence the answer is 1 correct?


"I have not failed, I have found 10,000 ways that will not work" -Edison

Offline

Board footer

Powered by FluxBB