Shell String Function – Write a Function to Check if a String Starts with or Contains Something

functionpattern matchingshellstring

I want to write a function that checks if a given variable, say, var, starts with any of the words in a given list of strings. This list won't change.

To instantiate, let's pretend that I want to check if var starts with aa, abc or 3@3.

Moreover, I want to check if var contains the character >.

Let's say this function is called check_func. My intended usage looks something like

if check_func "$var"; then
    do stuff
fi

For example, it should "do stuff" for
aardvark, abcdef, 3@3com.com and 12>5.


I've seen this SO question where a user provides part of the work:

beginswith() { case $2 in "$1"*) true;; *) false;; esac; }

My idea is that I would iterate over the list mentioned above and use this function. My difficulty lies in not understanding exactly how exiting (or whatever replaces returning) should be done to make this work.

Best Answer

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)

Related Question