Reputation: 2681
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
Upvotes: 189
Views: 340154
Reputation: 9
To check if a variable contains a fixed-string i'm using this method :
if [ "$ALPHABET" != "${ALPHABET#*CDDE}" ]; then
echo "the ALPHABET contains 'CDDE' string"
else
echo "there is no 'CDDE' string in ALPHABET variable"
fi
To understand it more easily :
#!/bin/sh
LANG=C
ALPHABET="AABBCCDDEE"
EXAMPLE_1="${ALPHABET#*B}"
EXAMPLE_2="${ALPHABET##*B}"
EXAMPLE_3="${ALPHABET%B*}"
EXAMPLE_4="${ALPHABET%%B*}"
# The flag '#' operates for the shortest prefix
# The flag '##' operates for the longest prefix
# The flag '%' operates for the shortest suffix
# The flag '%%' operates for the longest suffix
echo $EXAMPLE_1 # BCCDDEE
echo $EXAMPLE_2 # CCDDEE
echo $EXAMPLE_3 # AAB
echo $EXAMPLE_4 # AA
Upvotes: 0
Reputation: 808
STRING="String to test"
SUBSTRING="test"
if [ $(echo $STRING|grep $SUBSTRING|wc -l) -ne 0 ]
then
echo "exists"
fi
Upvotes: 0
Reputation: 331
Since I didn't see the example of how I've done it... Here's my contribution.
#!/bin/sh
thiscmd="java $@"
javasubstr=" -jar "
if [ -z "${thiscmd##*$javasubstr*}" ]; then
#it exists
fi
Upvotes: 0
Reputation: 2549
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 '*\`[]' '\`'
Upvotes: 228
Reputation: 11
This is another possible POSIX solution based on this answer, but making it work with special characters, like []*
. This is achieved surrounding the substring
variable with double quotes.
This is an alternative implementation of this other answer on another thread using only shell builtins. If string
is empty the last test
would give a false positive, hence we need to test whether substring
is empty as well in that case.
#!/bin/sh
# contains(string, substring)
#
# Returns 0 if the specified string contains the specified substring,
# otherwise returns 1.
contains() {
string="$1"
substring="$2"
test -n "$string" || test -z "$substring" && test -z "${string##*"$substring"*}"
}
Or one-liner:
contains() { test -n "$1" || test -z "$2" && test -z "${1##*"$2"*}"; }
Nevertheless, a solution with case
like this other answer looks simpler and less error prone.
#!/bin/sh
contains() {
string="$1"
substring="$2"
case "$string" in
*"$substring"*) true ;;
*) false ;;
esac
}
Or one-liner:
contains() { case "$1" in *"$2"*) true ;; *) false ;; esac }
For the tests:
contains "abcd" "e" || echo "abcd does not contain e"
contains "abcd" "ab" && echo "abcd contains ab"
contains "abcd" "bc" && echo "abcd contains bc"
contains "abcd" "cd" && echo "abcd contains cd"
contains "abcd" "abcd" && echo "abcd contains abcd"
contains "" "" && echo "empty string contains empty string"
contains "a" "" && echo "a contains empty string"
contains "" "a" || echo "empty string does not contain a"
contains "abcd efgh" "cd ef" && echo "abcd efgh contains cd ef"
contains "abcd efgh" " " && echo "abcd efgh contains a space"
contains "abcd [efg] hij" "[efg]" && echo "abcd [efg] hij contains [efg]"
contains "abcd [efg] hij" "[effg]" || echo "abcd [efg] hij does not contain [effg]"
contains "abcd *efg* hij" "*efg*" && echo "abcd *efg* hij contains *efg*"
contains "abcd *efg* hij" "d *efg* h" && echo "abcd *efg* hij contains d *efg* h"
contains "abcd *efg* hij" "*effg*" || echo "abcd *efg* hij does not contain *effg*"
Upvotes: 1
Reputation: 100133
There's Bash regular expressions. Or there's 'expr':
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
Upvotes: 6
Reputation: 6891
In special cases where you want to find whether a word is contained in a long text, you can iterate through the long text with a loop.
found=F
query_word=this
long_string="many many words in this text"
for w in $long_string; do
if [ "$w" = "$query_word" ]; then
found=T
break
fi
done
This is pure Bourne shell.
Upvotes: 2
Reputation:
See the manpage for the 'test' program. If you're just testing for the existence of a directory you would normally do something like so:
if test -d "String1"; then
echo "String1 present"
end
If you're actually trying to match a string you can use bash expansion rules & wildcards as well:
if test -d "String*"; then
echo "A directory starting with 'String' is present"
end
If you need to do something more complex you'll need to use another program like expr.
Upvotes: 2
Reputation: 1231
#!/usr/bin/env sh
# Searches a subset string in a string:
# 1st arg:reference string
# 2nd arg:subset string to be matched
if echo "$1" | grep -q "$2"
then
echo "$2 is in $1"
else
echo "$2 is not in $1"
fi
Upvotes: 55
Reputation: 1086
Here is a link to various solutions of your issue.
This is my favorite as it makes the most human readable sense:
The Star Wildcard Method
if [[ "$string" == *"$substring"* ]]; then
return 1
fi
return 0
Upvotes: 10
Reputation: 6872
Sadly, I am not aware of a way to do this in sh. However, using bash (starting in version 3.0.0, which is probably what you have), you can use the =~ operator like this:
#!/bin/bash
CURRENT_DIR=`pwd`
if [[ "$CURRENT_DIR" =~ "String1" ]]
then
echo "String1 present"
elif [[ "$CURRENT_DIR" =~ "String2" ]]
then
echo "String2 present"
else
echo "Else"
fi
As an added bonus (and/or a warning, if your strings have any funny characters in them), =~ accepts regexes as the right operand if you leave out the quotes.
Upvotes: 37
Reputation: 137
If you want a ksh only method that is as fast as "test", you can do something like:
contains() # haystack needle
{
haystack=${1/$2/}
if [ ${#haystack} -ne ${#1} ] ; then
return 1
fi
return 0
}
It works by deleting the needle in the haystack and then comparing the string length of old and new haystacks.
Upvotes: 3
Reputation:
test $(echo "stringcontain" "ingcon" |awk '{ print index($1, $2) }') -gt 0 && echo "String 1 contain string 2"
--> output: String 1 contain string 2
Upvotes: 2
Reputation: 62244
case $(pwd) in
*path) echo "ends with path";;
path*) echo "starts with path";;
*path*) echo "contains path";;
*) echo "this is the default";;
esac
Upvotes: 20
Reputation: 202615
Pure POSIX shell:
#!/bin/sh
CURRENT_DIR=`pwd`
case "$CURRENT_DIR" in
*String1*) echo "String1 present" ;;
*String2*) echo "String2 present" ;;
*) echo "else" ;;
esac
Extended shells like ksh or bash have fancy matching mechanisms, but the old-style case
is surprisingly powerful.
Upvotes: 123