How to check if a string contains a substring in B

2018-12-31 07:12发布

I have a string in Bash:

string="My string"

How can I test if it contains another string?

if [ $string ?? 'foo' ]; then
  echo "It's there!"
fi

Where ?? is my unknown operator. Do I use echo and grep?

if echo "$string" | grep 'foo'; then
  echo "It's there!"
fi

That looks a bit clumsy.

21条回答
后来的你喜欢了谁
2楼-- · 2018-12-31 07:33

I like sed.

substr="foo"
nonsub="$(echo "$string" | sed "s/$substr//")"
hassub=0 ; [ "$string" != "$nonsub" ] && hassub=1

Edit, Logic:

  • Use sed to remove instance of substring from string

  • If new string differs from old string, substring exists

查看更多
心情的温度
3楼-- · 2018-12-31 07:34

My .bash_profile and how I used grep if the PATH included my 2 bin dirs, don't append them

# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

U=~/.local.bin:~/bin

if ! echo "$PATH" | grep -q "home"; then
    export PATH=$PATH:${U}   
fi
查看更多
十年一品温如言
4楼-- · 2018-12-31 07:36

Bash4+ examples. Note: not using quotes will cause issues when words contain spaces etc.. Always quote in bash IMO.

Here are some examples BASH4+ :

Example 1, check for 'yes' in string (case insensitive):

    if [[ "${str,,}" == *"yes"* ]] ;then

Example 2, check for 'yes' in string (case insensitive):

    if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

Example 3, check for 'yes' in string (case sensitive) :

     if [[ "${str}" == *"yes"* ]] ;then

Example 4, check for 'yes' in string (case sensitive):

     if [[ "${str}" =~ "yes" ]] ;then

Example 5, exact match (case sensitive):

     if [[ "${str}" == "yes" ]] ;then

Example 6, exact match (case insensitive):

     if [[ "${str,,}" == "yes" ]] ;then

Example 7, exact match :

     if [ "$a" = "$b" ] ;then

Example 8, wildcard match .ext (case insensitive) :

     if echo "$a" | egrep -iq "\.(mp[3-4]|txt|css|jpg|png)" ; then

enjoy.

查看更多
长期被迫恋爱
5楼-- · 2018-12-31 07:37

The accepted answer is best, but since there's more than one way to do it, here's another solution:

if [ "$string" != "${string/foo/}" ]; then
    echo "It's there!"
fi

${var/search/replace} is $var with the first instance of search replaced by replace, if it is found (it doesn't change $var). If you try to replace foo by nothing, and the string has changed, then obviously foo was found.

查看更多
宁负流年不负卿
6楼-- · 2018-12-31 07:37

So there are lots of useful solutions to the question - but which is fastest / uses the least resource?

Repeated tests using this frame:

/usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'

Replacing TEST each time:

[[ $b =~ $a ]]           2.92user 0.06system 0:02.99elapsed 99%CPU

[ "${b/$a//}" = "$b" ]   3.16user 0.07system 0:03.25elapsed 99%CPU

[[ $b == *$a* ]]         1.85user 0.04system 0:01.90elapsed 99%CPU

case $b in *$a):;;esac   1.80user 0.02system 0:01.83elapsed 99%CPU

doContain $a $b          4.27user 0.11system 0:04.41elapsed 99%CPU

(doContain was in F. Houri's answer)

And for giggles:

echo $b|grep -q $a       12.68user 30.86system 3:42.40elapsed 19%CPU !ouch!

So the simple substituion option predicatbly wins whether in an extended test or a case. The case is portable.

Piping out to 100000 greps is predictably painful! The old rule about using external utilities without need holds true.

查看更多
残风、尘缘若梦
7楼-- · 2018-12-31 07:37

One is:

[ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' ||  echo 'no'
查看更多
登录 后发表回答