我在Bash中有一个字符串:

string="My string"

如何测试它是否包含另一个字符串?

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

哪里是我不认识的接线员。我使用echo和grep吗?

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

这看起来有点笨拙。


当前回答

字符串包含变量(兼容或不区分大小写)

由于这些Stack Overflow的答案主要讲述了Bash,我在这篇文章的底部发布了一个独立于大小写的Bash函数。。。

总之,有我的

兼容答案

由于已经有很多使用Bash特定功能的答案,因此有一种方法可以在功能较差的shell下工作,例如BusyBox:

[ -z "${string##*$reqsubstr*}" ]

在实践中,这可能会:

string='echo "My string"'
for reqsubstr in 'o "M' 'alt' 'str';do
  if [ -z "${string##*$reqsubstr*}" ] ;then
      echo "String '$string' contain substring: '$reqsubstr'."
    else
      echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
  done

这是在Bash、Dash、KornShell(ksh)和ash(BusyBox)下测试的,结果总是:

String 'echo "My string"' contain substring: 'o "M'.
String 'echo "My string"' don't contain substring: 'alt'.
String 'echo "My string"' contain substring: 'str'.

集成到一个函数中

正如@EeroAaltonen所问,这里是相同演示的一个版本,在相同的外壳下测试:

myfunc() {
    reqsubstr="$1"
    shift
    string="$@"
    if [ -z "${string##*$reqsubstr*}" ] ;then
        echo "String '$string' contain substring: '$reqsubstr'.";
      else
        echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
}

然后:

$ myfunc 'o "M' 'echo "My String"'
String 'echo "My String"' contain substring 'o "M'.

$ myfunc 'alt' 'echo "My String"'
String 'echo "My String"' don't contain substring 'alt'.

注意:必须转义或双引号和/或双引号:

$ myfunc 'o "M' echo "My String"
String 'echo My String' don't contain substring: 'o "M'.

$ myfunc 'o "M' echo \"My String\"
String 'echo "My String"' contain substring: 'o "M'.

简单的功能

这是在BusyBox、Dash和Bash下测试的:

stringContain() { [ -z "${2##*$1*}" ]; }

现在:

$ if stringContain 'o "M3' 'echo "My String"';then echo yes;else echo no;fi
no
$ if stringContain 'o "M' 'echo "My String"';then echo yes;else echo no;fi
yes

…或者,如果提交的字符串可能为空,如@Sjlver所指出的,则函数将变为:

stringContain() { [ -z "${2##*$1*}" ] && [ -z "$1" -o -n "$2" ]; }

或者正如Adrian Günter的评论所建议的,避免使用-o开关:

stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ];};}

最终(简单)功能:

并反转测试以使其可能更快:

stringContain() { [ -z "$1" ] || { [ -z "${2##*$1*}" ] && [ -n "$2" ];};}

对于空字符串:

$ if stringContain '' ''; then echo yes; else echo no; fi
yes
$ if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

独立于大小写(仅限Bash!)

对于不区分大小写的字符串测试,只需将每个字符串转换为小写:

stringContain() {
    local _lc=${2,,}
    [ -z "$1" ] || { [ -z "${_lc##*${1,,}*}" ] && [ -n "$2" ] ;} ;}

检查:

stringContain 'o "M3' 'echo "my string"' && echo yes || echo no
no
stringContain 'o "My' 'echo "my string"' && echo yes || echo no
yes
if stringContain '' ''; then echo yes; else echo no; fi
yes
if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

其他回答

我不确定是否使用if语句,但您可以使用case语句获得类似的效果:

case "$string" in 
  *foo*)
    # Do stuff
    ;;
esac

grep-q对于这个目的很有用。

同样使用awk:

string="unix-bash 2389"
character="@"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

输出:

未找到

string="unix-bash 2389"
character="-"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

输出:

建立

原始来源:http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html

使用jq:

string='My long string'
echo $string | jq -Rr 'select(contains("long"))|"It is there"'

jq中最困难的事情是打印单个引用:

echo $string | jq --arg quote "'" -Rr 'select(contains("long"))|"It\($quote)s there"'

仅使用jq检查条件:

if jq -Re 'select(contains("long"))|halt' <<< $string; then
    echo "It's there!"
fi

Bash 4+示例。注意:当单词包含空格等时,不使用引号会导致问题。请始终在Bash、IMO中引用。

以下是一些Bash 4+示例:

示例1,检查字符串中的“yes”(不区分大小写):

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

示例2,检查字符串中的“yes”(不区分大小写):

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

示例3,检查字符串中的“yes”(区分大小写):

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

示例4,检查字符串中的“yes”(区分大小写):

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

示例5,完全匹配(区分大小写):

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

示例6,完全匹配(不区分大小写):

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

示例7,完全匹配:

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

示例8,通配符match.ext(不区分大小写):

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

示例9,对区分大小写的字符串使用grep:

     if echo "SomeString" | grep -q "String"; then

示例10,对不区分大小写的字符串使用grep:

     if echo "SomeString" | grep -iq "string"; then

示例11,对字符串使用grep,不区分大小写,带通配符:

     if echo "SomeString" | grep -iq "Some.*ing"; then

示例12,使用doublehash进行比较(如果变量为空会导致假阳性等)(区分大小写):

     if [[ ! ${str##*$substr*} ]] ;then  #found

享受

我使用这个函数(一个不包括但很明显的依赖项)。它通过了以下测试。如果函数返回值>0,则找到字符串。你也可以很容易地返回1或0。

function str_instr {
   # Return position of ```str``` within ```string```.
   # >>> str_instr "str" "string"
   # str: String to search for.
   # string: String to search.
   typeset str string x
   # Behavior here is not the same in bash vs ksh unless we escape special characters.
   str="$(str_escape_special_characters "${1}")"
   string="${2}"
   x="${string%%$str*}"
   if [[ "${x}" != "${string}" ]]; then
      echo "${#x} + 1" | bc -l
   else
      echo 0
   fi
}

function test_str_instr {
   str_instr "(" "'foo@host (dev,web)'" | assert_eq 11
   str_instr ")" "'foo@host (dev,web)'" | assert_eq 19
   str_instr "[" "'foo@host [dev,web]'" | assert_eq 11
   str_instr "]" "'foo@host [dev,web]'" | assert_eq 19
   str_instr "a" "abc" | assert_eq 1
   str_instr "z" "abc" | assert_eq 0
   str_instr "Eggs" "Green Eggs And Ham" | assert_eq 7
   str_instr "a" "" | assert_eq 0
   str_instr "" "" | assert_eq 0
   str_instr " " "Green Eggs" | assert_eq 6
   str_instr " " " Green "  | assert_eq 1
}