Search code examples
shellunix

How do you tell if a string contains another string in POSIX sh?


I want to write a Unix shell script that will do various logic if there is a string inside of another string. For example, if I am in a certain folder, branch off. Could someone please tell me how to accomplish this? If possible I would like to make this not shell specific (i.e. not bash only) but if there's no other way I can make do with that.

#!/usr/bin/env sh

if [ "$PWD" contains "String1" ]
then
    echo "String1 present"
elif [ "$PWD" contains "String2" ]
then
    echo "String2 present"
else
    echo "Else"
fi

Solution

  • Here's yet another solution. This uses POSIX substring parameter expansion, so it works in Bash, Dash, KornShell (ksh), Z shell (zsh), etc. It also supports special characters in strings.

    test "${string#*"$word"}" != "$string" && echo "$word found in $string"
    

    A functionalized version with some tests:

    # contains(string, substring)
    #
    # Returns 0 if the specified string contains the specified substring,
    # otherwise returns 1.
    contains() {
        string="$1"
        substring="$2"
        if [ "${string#*"$substring"}" != "$string" ]; then
            return 0    # $substring is in $string
        else
            return 1    # $substring is not in $string
        fi
    }
    
    testcontains() {
        testnum="$1"
        expected="$2"
        string="$3"
        substring="$4"
        contains "$string" "$substring"
        result=$?
        if [ $result -eq $expected ]; then
            echo "test $testnum passed"
        else
            echo "test $testnum FAILED: string=<$string> substring=<$substring> result=<$result> expected=<$expected>"
        fi
    }
    
    testcontains  1 1 'abcd' 'e'
    testcontains  2 0 'abcd' 'ab'
    testcontains  3 0 'abcd' 'bc'
    testcontains  4 0 'abcd' 'cd'
    testcontains  5 0 'abcd' 'abcd'
    testcontains  6 1 '' 'a'
    testcontains  7 0 'abcd efgh' 'cd ef'
    testcontains  8 0 'abcd efgh' ' '
    testcontains  9 1 'abcdefgh' ' '
    testcontains 10 0 'abcd [efg] hij' '[efg]'
    testcontains 11 1 'abcd [efg] hij' '[effg]'
    testcontains 12 0 'abcd *efg* hij' '*efg*'
    testcontains 13 0 'abcd *efg* hij' 'd *efg* h'
    testcontains 14 1 'abcd *efg* hij' '*effg*'
    testcontains 15 1 'abcd *efg* hij' '\effg\'
    testcontains 16 0 'a\b' '\'
    testcontains 17 0 '\' '\'
    testcontains 18 1 '[' '\'
    testcontains 19 1 '\' '['
    testcontains 20 0 '-n' 'n'
    testcontains 21 1 'n' '-n'
    testcontains 22 0 '*\`[]' '\`'