Differences between revisions 1 and 20 (spanning 19 versions)
Revision 1 as of 2007-05-02 23:37:18
Size: 2011
Editor: redondos
Comment:
Revision 20 as of 2023-04-29 04:33:04
Size: 2010
Editor: ormaaj
Comment: >:-|
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
[[Anchor(faq46)]] <<Anchor(faq46)>>
Line 3: Line 3:
If your real question is ''How do I check whether one of my parameters was -v?'' then see [[BashFAQ/035|FAQ #35]] instead. Otherwise, read on…
Line 4: Line 5:
The safest way to do this would be to loop over all elements in your set/list and check them for the element/word you are looking for. Say we are looking for the content of bar in the array foo:
   {{{
   for element in "${foo[@]}"; do
      [[ $element = $bar ]] && echo "Found $bar."
   done}}}
<<TableOfContents>>
=== Associative arrays ===
All we need to do is create an entry for each item and look it up by index. In this example, we test whether the user input `x` is a member of the set `a`:
Line 10: Line 9:
Or, to stop searching when you find it:
   {{{
   for element in "${foo[@]}"; do
      [[ $element = $bar ]] && { echo "Found $bar."; break; }
   done}}}
{{{
# Bash etc.
Line 16: Line 12:
If for some reason your list/set is not in an array, but is a string of words, and the element you are searching for is also a word, you can use this:
   {{{
   for element in $foo; do
      [[ $element = $bar ]] && echo "Found $bar."
   done}}}
function get_input {
 [[ -t 0 ]] || return
 printf 'hm? '
 IFS= read -r${BASH_VERSION+\e} -- "$1"
}
Line 22: Line 18:
A less safe, but more clever version:
   {{{
   if [[ " $foo " = *\ "$bar"\ * ]]; then
      echo "Found $bar."
   fi}}}
set -- Bigfoot UFOs Republicans
typeset -A a
for x; do
 a+=([$x]=)
done
Line 28: Line 24:
And, if for some reason you don't know the syntax of for well enough, here's how to check your script's parameters for an element. For example, '-v':
   {{{
   for element; do
      [[ $element = '-v' ]] && echo "Switching to verbose mode."
   done}}}
get_input x
Line 34: Line 26:
GNU's grep has a {{{\b}}} feature which allegedly matches the edges of words. Using that, one may attempt to replicate the "clever" approach used above, but it is fraught with peril: if [[ -v a[$x] ]]; then
 printf '%s exists!\n' "$x"
else
 printf $'%s doesn\'t exist.\\n' "$x"
fi
}}}
Line 36: Line 33:
   {{{
   # Is 'foo' one of the positional parameters?
   egrep '\bfoo\b' <<<"$@" >/dev/null && echo yes
   # This is where it fails: is '-v' one of the positional parameters?
   egrep '\b-v\b' <<<"$@" >/dev/null && echo yes
   # Unfortunately, \b sees "v" as a separate word.
   # Nobody knows what the hell it's doing with the "-".
=== Indexed arrays ===
We can store a list of strings in an indexed array by looping over each element:
Line 44: Line 36:
   # Is "someword" in the array 'array'?
   egrep '\bsomeword\b' <<<"${array[@]}"
   # Obviously, you can't use this if someword is '-v'!}}}
 
Since this "feature" of GNU grep is both non-portable and poorly defined, we don't recommend using it.
   
{{{
# Bash

typeset -a haystack
for x in "${haystack[@]}"; do
 [[ $x == "$needle" ]] && printf 'Found %q!\n' "$needle"
done
}}}

=== enum (ksh93) ===
In ksh93t or later, one may create enum types/variables/constants using the `enum` builtin. These work similarly to C enums (and the equivalent feature of other languages). These may be used to restrict which values may be assigned to a variable so as to avoid the need for an expensive test each time an array variable is set or referenced. Like types created using `typeset -T`, the result of an `enum` command is a new declaration command that can be used to instantiate objects of that type.

{{{
# ksh93

 $ enum colors=(red green blue)
 $ colors foo=green
 $ foo=yellow
ksh: foo: invalid value yellow
}}}

`typeset -a` can also be used in combination with an enum type to allow enum constants as subscripts.

{{{
# ksh93

 $ typeset -a '[colors]' bar
 $ bar[blue]=test1
 $ typeset -p bar
typeset -a '[colors]' bar=([blue]=test)
 $ bar[orange]=test
ksh: colors: invalid value orange
}}}

----
CategoryShell

I want to check to see whether a word is in a list (or an element is a member of a set).

If your real question is How do I check whether one of my parameters was -v? then see FAQ #35 instead. Otherwise, read on…

Associative arrays

All we need to do is create an entry for each item and look it up by index. In this example, we test whether the user input x is a member of the set a:

# Bash etc.

function get_input {
        [[ -t 0 ]] || return
        printf 'hm? '
        IFS= read -r${BASH_VERSION+\e} -- "$1"
}

set -- Bigfoot UFOs Republicans
typeset -A a
for x; do
        a+=([$x]=)
done

get_input x

if [[ -v a[$x] ]]; then
        printf '%s exists!\n' "$x"
else
        printf $'%s doesn\'t exist.\\n' "$x"
fi

Indexed arrays

We can store a list of strings in an indexed array by looping over each element:

# Bash

typeset -a haystack
for x in "${haystack[@]}"; do
        [[ $x == "$needle" ]] && printf 'Found %q!\n' "$needle"
done

enum (ksh93)

In ksh93t or later, one may create enum types/variables/constants using the enum builtin. These work similarly to C enums (and the equivalent feature of other languages). These may be used to restrict which values may be assigned to a variable so as to avoid the need for an expensive test each time an array variable is set or referenced. Like types created using typeset -T, the result of an enum command is a new declaration command that can be used to instantiate objects of that type.

# ksh93

 $ enum colors=(red green blue)
 $ colors foo=green
 $ foo=yellow
ksh: foo:  invalid value yellow

typeset -a can also be used in combination with an enum type to allow enum constants as subscripts.

# ksh93

 $ typeset -a '[colors]' bar
 $ bar[blue]=test1
 $ typeset -p bar
typeset -a '[colors]' bar=([blue]=test)
 $ bar[orange]=test
ksh: colors:  invalid value orange


CategoryShell

BashFAQ/046 (last edited 2023-04-29 04:33:04 by ormaaj)