Write a function that checks if a string starts with or contains something

check_prefixes () {
    value=$1

    for prefix in aa abc 3@3; do
        case $value in
            "$prefix"*) return 0
        esac
    done

    return 1
}

check_contains_gt () {
    value=$1

    case $value in
        *">"*) return 0
    esac

    return 1
}

var='aa>'
if check_prefixes "$var" && check_contains_gt "$var"; then
    printf '"%s" contains ">" and starts with one of the prefixes\n' "$var"
fi

I divided the tests up into two functions. Both use case ... esac and returns success (zero) as soon as this can be determined. If nothing matches, failure (1) is returned.

To make the list of prefixes more of a dynamic list, one could possibly write the first function as

check_prefixes () {
    value=$1
    shift

    for prefix do
        case $value in
            "$prefix"*) return 0
        esac
    done

    return 1
}

(the value to inspect is the first argument, which we save in value and then shift off the list of arguments to the function; we then iterate over the remaining arguments) and then call it as

check_prefixes "$var" aa abc 3@3

The second function could be changed in a similar manner, into

check_contains () {
    value=$1
    shift

    case $value in
        *"$1"*) return 0
    esac

    return 1
}

(to check for some arbitrary substring), or

check_contains_oneof () {
    value=$1
    shift

    for substring do
        case $value in
            *"$substring"*) return 0
        esac
    done

    return 1
}

(to check for any of a number of substrings)


For bash:

Using the properties of regex you can write start with ^ and contain by nothing.

The list of regexes to check start with aa abc or 3@3 and contains > is:

^aa ^abc ^3@3 >

Make that a properly quoted list and ask bash to use regexes (=~):

check_func() {
               matched=1
               for test_regex in '^aa' '^abc' '^3@3' '>'; do
                   if [[ $var =~ $test_regex ]] ; then
                       matched=0
                       break 
                   fi
               done
               return "$matched"
              }

var='aaIsAMatch'
if check_func; then
    echo "A match was found"
fi

The function has hard-coded the list of matches and the name of the var.

Giving the list of regex in an array variable and the value to test on the first argument:

check_func() {
               local matched; matched=1
               for t in "${test_regex[@]}"; do
                   [[ $1 =~ $t ]] && { matched=0; break; } 
               done
               return "$matched"
              }


test_regex=('^aa' '^abc' '^3@3' '>')

if check_func 'aaIsAMatch'; then
    echo "A match was found"
fi

The function could be further improved to use the name of a variable (instead of a value) as the first argument.

posix

As there is no regex in posix shells and the only way to test is a case statement, we must use a case statement. Sadly, for older shells ([no extended globs available][1]) we must loop to make all tests. And, the globs need to be:

'aa*' 'abc*' '3@3*' '*>*'

An script example that tests several input strings against several globs:

check_func() { :
           matched=1
       value=$1; shift
           for t in "$@"; do
               case $value in $t) matched=0; #break;; esac
                  echo "matched $value with $t"
                  ;;
       esac
       done
           return "$matched"
         }


for var in abdg wabcde aadef abcde 3@3hello hmm3@3hell 'we>we' 'a>dfff' 'dfd>' 'a> de' 'a*> fg'; do
if check_func "$var" 'aa*' 'abc*' '3@3*' '*>*'; then
        echo "========A match was found for \"$var\""
fi
done

A simpler version of the function to exactly match your request:

check_func() { :
               matched=1
               value=$1; shift
                   for t in "$@"; do
                       case $value in $t) matched=0; break;; esac
                   done
               return "$matched"
             }

Here's what the case statement does: take the second parameter to the function ($2). If it matches the pattern "$1"*, i.e. the first argument to the function followed by anything, then execute true and end the case statement. true does nothing and returns the status 0. Otherwise, if it matches *, i.e. anything, execute false and end the case statement. false does nothing and returns the status 1. Thus the case statement has the status 0 if the second parameter starts with the first parameter and 1 otherwise. Since this is the last (and only) statement in the function, the function returns 0 if the second parameter starts with the first parameter and 1 otherwise.

Conditional statements such as if in the shell consider a statement to be true if it returns 0 and false otherwise. Hence if beginswith "$var" "string"; then echo yes; else echo no; fi prints yes if the value of var starts with string and no otherwise.

There are several alternative ways to write this function. For example the author could have used return 0 or return 1 instead of true and false, since they are the last statement in the function. The way the function was written makes it possible to use its body directly without wrapping it in a function, by just changing references to the function parameters ($1 and $2) to whatever strings you want to work with.

To allow multiple prefixes, iterate over them in a loop. As soon as you've found a matching prefix, return from the function, with a true status (0). If none of the prefixes match, return a false status (conventionally 1).

# begins_with STRING PREFIX1 PREFIX2...
# Test if STRING starts with any of PREFIX1, PREFIX2, ...
begins_with () {
  string=$1
  shift
  for prefix in "$@"; do
    case "$string" in
      "$prefix"*) return 0;;
    esac
  done
  return 1
}

if begins_with "$var" 'aa' 'abc' '3@3'; then
  echo "The value starts with one of the permitted prefixes"
fi

To test for a suffix, use the pattern *"$suffix" instead of "$prefix"*. To test for a substring, use *"$substring"*. Note that the double quotes are necessary here, otherwise the variable would be interpreted as a pattern. For example:

suffix='?'
case "$var" in
  *"$suffix") echo "The value of var ends with a question mark";; 
esac
case "$var" in
  *$suffix) echo "The value of var is not empty";; 
esac