如何确定一个字符串是否是bash中另一个字符串的子字符串?


49

我想看看一个字符串是否在另一个字符串的一部分内。
例如:

'ab' in 'abc' -> true
'ab' in 'bcd' -> false

如何在bash脚本的条件下执行此操作?

Answers:


27

您可以使用以下形式${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

之所以起作用,${VAR/subs}是因为它等于,$VAR但第一次subs删除了字符串,特别是如果$VAR不包含该单词subs,则不会对其进行修改。


我认为您应该更改echo语句的顺序。因为我得到了ab is not in abc
Lucio

你是对的!:P
埃德温

嗯..不,脚本是错误的。这样我得到了ab was found in abc,但是如果我使用,substring=z我得到了z was found in abc
Lucio

1
现在我明白了ab is not in abc。但是z was found in abc。这很有趣:D
Lucio

1
!回声恰好在此开始!XD
埃德温

47

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

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

所以你可以使用这种形式像

var1="ab"
var2="bcd"
if [[ "$var2" =~ "$var1" ]]; then
    echo "pass"
else
    echo "fail"
fi

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


1
我得到fail了以下参数:var2="abcd"
Lucio

3
@Lucio正确的是[[ $string =~ $substring ]]。我更新了答案。
埃里克·卡瓦略

12

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

substr=ab
[[ abc == *"$substr"* ]] && echo yes || echo no    # yes
[[ bcd == *"$substr"* ]] && echo yes || echo no    # no

如果[[“ $ JAVA_OPTS”!= “ -XX:+ UseCompressedOops” ]]; 然后导出JAVA_OPTS =“ $ JAVA_OPTS -XX:+ UseCompressedOops”; fi
Mike Slinn '16

10

以下两种方法不仅可以在bash中使用,而且可以在任何POSIX兼容环境中使用:

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
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

以上两个输出:

'abc' contains 'ab'
'bcd' does not contain 'ab'

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

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


第一个版本非常适合xrandr在变量中存储的监视器名称列表中查找监视器名称的子字符串。+1并欢迎加入1K代表俱乐部:)
WinEunuuchs2Unix

6

外壳案例声明

这是最便携式的解决方案,即使在旧的Bourne外壳和Korn外壳上也可以使用

#!/bin/bash
case "abcd" in
    *$1*) echo "It's a substring" ;;
    *) echo "Not a substring" ;;
esac

样品运行:

$ ./case_substr.sh "ab"                                                                                           
It's a substring
$ ./case_substr.sh "whatever"                                                                                     
Not a substring

请注意,您不必专门使用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 $@

grep

$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"                                    
it's a substring

这种特殊方法对于中的if-else语句很有用bash。也大多是便携式的

AWK

$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"                                                             
it is a substring

蟒蛇

$ 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

红宝石

$ ruby -e ' puts "is substring" if  ARGV[1].include? ARGV[0]'  "ab" "abcdef"                                             
is substring

超越他人超越+1。我在这里和其他堆栈交换站点上注意到,没有答案返回字符串中子字符串的偏移量。这是今晚的任务:)
WinEunuuchs2Unix

@ WinEunuuchs2Unix要在bash中做到这一点?
Sergiy Kolodyazhnyy

是的,不是。我正在做一个科学怪人项目,其中python获取所有gmail.com消息元数据,bash对其进行解析,并提供带有向下钻取的GUI列表。我在这里找到了答案:stackoverflow.com/questions/5031764/…–
WinEunuuchs2Unix

@ WinEunuuchs2Unix确定。听起来不错。我个人更喜欢用Python解析所有内容。它具有比单独bash强大的文本处理功能。
Sergiy Kolodyazhnyy

我知道您的偏好大约两年了,我尊重他们。但是我只是在学习Python,让Yad在其中工作对我来说似乎很麻烦。更不用说我已经对bash满意的所有数组处理。但是至少我写了我的第一个python脚本,将所有内容从Google的gmail.com中吸进Linux平面文件中,对吗?:)
WinEunuuchs2Unix

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).

因此,就像@glenn_jackman所说的那样,但请注意,如果将整个第二项用双引号引起来,它将把测试切换为文字匹配。

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


4

与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

输出:

abc contains ab
bcd does NOT contain ab
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.