How to determine if a string is a substring of another in bash?

Luc*_*cio 51 command-line bash scripts

I want to see if a string is inside a portion of another string.
e.g.:

'ab' in 'abc' -> true
'ab' in 'bcd' -> false
Run Code Online (Sandbox Code Playgroud)

How can I do this in a conditional of a bash script?

dem*_*ure 48

[[ "bcd" =~ "ab" ]]
[[ "abc" =~ "ab" ]]

括号用于测试,由于它是双括号,因此可以进行一些额外的测试,例如=~.

所以你可以使用这种形式

var1="ab"
var2="bcd"
if [[ "$var2" =~ "$var1" ]]; then
    echo "pass"
else
    echo "fail"
fi
Run Code Online (Sandbox Code Playgroud)

编辑:更正了“=~”,已翻转。

  • @Lucio 正确的是`[[ $string =~ $substring ]]`。我更新了答案。 (3认同)

edw*_*win 29

您可以使用包含更大字符串的表单${VAR/subs}VAR并且 subs是您要查找的子字符串:

my_string=abc
substring=ab
if [ "${my_string/$substring}" = "$my_string" ] ; then
  echo "${substring} is not in ${my_string}"
else
  echo "${substring} was found in ${my_string}"
fi
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为${VAR/subs}等于$VARsubs删除了第一次出现的字符串,特别是如果$VAR不包含subs它不会被修改的单词。


gle*_*man 12

使用 bash文件名模式(又名“glob”模式)

substr=ab
[[ abc == *"$substr"* ]] && echo yes || echo no    # yes
[[ bcd == *"$substr"* ]] && echo yes || echo no    # no
Run Code Online (Sandbox Code Playgroud)


Ric*_*sen 10

以下两种方法适用于任何兼容 POSIX 的环境,而不仅仅是在 bash 中:

substr=ab
for s in abc bcd; do
    if case ${s} in *"${substr}"*) true;; *) false;; esac; then
        printf %s\\n "'${s}' contains '${substr}'"
    else
        printf %s\\n "'${s}' does not contain '${substr}'"
    fi
done
Run Code Online (Sandbox Code Playgroud)
substr=ab
for s in abc bcd; do
    if printf %s\\n "${s}" | grep -qF "${substr}"; then
        printf %s\\n "'${s}' contains '${substr}'"
    else
        printf %s\\n "'${s}' does not contain '${substr}'"
    fi
done
Run Code Online (Sandbox Code Playgroud)

以上两个输出:

'abc' contains 'ab'
'bcd' does not contain 'ab'
Run Code Online (Sandbox Code Playgroud)

前者的优点是不产生单独的grep进程。

请注意,我使用printf %s\\n "${foo}"而不是echo "${foo}"因为如果它包含反斜杠echo可能会损坏${foo}


Ser*_*nyy 6

shell case 语句

这是最便携的解决方案,甚至可以在旧的 Bourne shell 和 Korn shell 上工作

#!/bin/bash
case "abcd" in
    *$1*) echo "It's a substring" ;;
    *) echo "Not a substring" ;;
esac
Run Code Online (Sandbox Code Playgroud)

示例运行:

$ ./case_substr.sh "ab"                                                                                           
It's a substring
$ ./case_substr.sh "whatever"                                                                                     
Not a substring
Run Code Online (Sandbox Code Playgroud)

请注意,您不必专门使用echo您可以使用exit 1exit 0来表示成功或失败。

我们还可以做的是创建一个具有特定返回值(匹配时为 0,不匹配时为 1)的函数(如有必要,可以在大型脚本中使用):

$ ./substring_function.sh                                  
ab is substring

$ cat substring_function.sh                                
#!/bin/sh

is_substring(){
    case "$2" in
        *$1*) return 0;;
        *) return 1;;
    esac
}

main(){
   if is_substring "ab" "abcdefg"
   then
       echo "ab is substring"
   fi
}

main $@
Run Code Online (Sandbox Code Playgroud)

格雷普

$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"                                    
it's a substring
Run Code Online (Sandbox Code Playgroud)

这种特殊方法对于bash. 也大多是便携式的

AWK

$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"                                                             
it is a substring
Run Code Online (Sandbox Code Playgroud)

Python

$ python -c 'import sys;sys.stdout.write("it is a substring") if "ab" in sys.stdin.read() else exit(1)' <<< "abcd"
it is a substring
Run Code Online (Sandbox Code Playgroud)

红宝石

$ ruby -e ' puts "is substring" if  ARGV[1].include? ARGV[0]'  "ab" "abcdef"                                             
is substring
Run Code Online (Sandbox Code Playgroud)


Cam*_*mpa 5

注意[["

[[ $a == z* ]]   # True if $a starts with an "z" (pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

[ $a == z* ]     # File globbing and word splitting take place.
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).
Run Code Online (Sandbox Code Playgroud)

正如@glenn_jackman 所说,但请注意,如果您将整个第二项用双引号括起来,它会将测试切换为文字匹配。

资料来源:http : //tldp.org/LDP/abs/html/comparison-ops.html


lau*_*ter 5

与 edwin 的答案类似,但改进了 posix 和 ksh 的可移植性,并且比 Richard 的噪音少一些:

substring=ab

string=abc
if [ "$string" != "${string%"$substring"*}" ]; then
    echo "$substring IS in $string"
else
    echo "$substring is NOT in $string"
fi

string=bcd
if [ "$string" != "${string%"$substring"*}" ]; then
    echo "$string contains $substring"
else
    echo "$string does NOT contain $substring"
fi
Run Code Online (Sandbox Code Playgroud)

输出:

abc contains ab
bcd does NOT contain ab
Run Code Online (Sandbox Code Playgroud)