我在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
这看起来有点笨拙。
我在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
这看起来有点笨拙。
您可以使用 马库斯的回答(*通配符) 在case语句之外,如果你使用双括号:
string='My long string'
if [[ $string = *"My long"* ]]; then
echo "It's there!"
fi
请注意,针串中的空格需要放在双引号之间,并且 *
通配符应该在外面。
如果您更喜欢正则表达式方法:
string='My string';
if [[ $string =~ .*My.* ]]
then
echo "It's there!"
fi
我不确定使用if语句,但是你可以使用case语句获得类似的效果:
case "$string" in
*foo*)
# Do stuff
;;
esac
由于已经有很多使用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
这是在测试下 庆典, 短跑, KSH 和 灰 (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所说,这是一个相同的演示版本,在相同的shell下测试:
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'.
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" ]; }
或者按照建议 AdrianGünter的评论,避免 -o
SwitchE的:
stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$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
您应该记住,shell脚本不是一种语言,而是一组命令。你本能地认为这种“语言”要求你遵循 if
用一个 [
或者a [[
。这两个只是返回退出状态的命令,指示成功或失败(就像所有其他命令一样)。因为这个原因我会用 grep
而不是 [
命令。
做就是了:
if grep -q foo <<<"$string"; then
echo "It's there"
fi
现在你正在考虑 if
测试其后面的命令的退出状态(以分号结尾)。为什么不重新考虑你正在测试的字符串的来源?
## Instead of this
filetype="$(file -b "$1")"
if grep -q "tar archive" <<<"$filetype"; then
#...
## Simply do this
if file -b "$1" | grep -q "tar archive"; then
#...
该 -q
选项使grep不输出任何内容,因为我们只需要返回代码。 <<<
使shell扩展下一个单词并将其用作命令的输入,该单行版本 <<
这里的文件(我不确定这是标准还是基础)。
接受的答案是最好的,但由于有多种方法可以做到这一点,这是另一种解决方案:
if [ "$string" != "${string/foo/}" ]; then
echo "It's there!"
fi
${var/search/replace}
是 $var
与第一个实例 search
取而代之 replace
,如果找到(它没有改变 $var
)。如果你试图更换 foo
什么都没有,而且字符串已经改变了,显然 foo
被找到。
所以这个问题有很多有用的解决方案 - 但哪个最快/使用最少的资源?
使用此框架重复测试:
/usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'
每次更换TEST:
[[ $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在F. Houri的回答中)
而对于咯咯地笑:
echo $b|grep -q $a 12.68user 30.86system 3:42.40elapsed 19%CPU !ouch!
因此,无论是在扩展测试还是案例中,简单替代选项都可以获得胜利。外壳是便携式的。
管道输出到100000 greps是可以预料的痛苦!关于无需使用外部实用程序的旧规则是正确的。