如何在Bourne Shell中检查子字符串

  • 本文关键字:字符串 Shell Bourne sh
  • 更新时间 :
  • 英文 :


我想测试字符串是否具有"子字符串"。在线大多数答案都是基于bash。我尝试了

if [ $string == "*substring*" ] 

不起作用。当前

if echo ${string} | grep -q "substring" 

工作。还有其他更好的方法吗?

使用POSIX符合参数 - 扩展和经典测试命令。

#!/bin/sh
substring=ab
string=abc
if [ "$string" != "${string%"$substring"*}" ]; then
    echo "$substring present in $string"
fi

(或)明确使用test操作员为

if test "$string" != "${string%$substring*}" ; then

在posix-features中,只有您将无法在条件enerm emen em ender pattern pattern pattern 模式>没有外部实用程序

也就是说:

  • Kenster的有用答案显示了如何使用case ... esac语句的分支进行模式匹配

  • inian的有用答案显示了如何在条件上使用 m匹配,使用模式作为参数扩展的一部分

您自己的grep方法肯定是一种选择,尽管您应该双重引用${string}

if echo "${string}" | grep -q "substring"; ...

一种更有效的方法是使用expr实用程序,但请注意,POSIX它仅限于Bres( basic 正则表达式),这是有限的:

string='This text contains the word "substring".'
if expr "$string" : ".*substring" >/dev/null; then echo "matched"; fi

请注意,正则表达式 - 第三操作数 - 隐式锚定在输入的 start 上,因此需要.*

>/dev/null抑制了 expr的默认输出,这是在这种情况下匹配的字符串的长度。(如果没有任何匹配,则输出为0,而退出代码设置为1)。

如果您只是在测试substring(或使用文件名通配符匹配的任何内容),则可以使用case

#!/bin/sh
while read line; do
    case "$line" in
    *foo*) echo "$line" contains foo ;;
    *bar*) echo "$line" contains bar ;;
    *)     echo "$line" isnt special ;;
    esac
done
$ ./testit.sh
food
food contains foo
ironbar
ironbar contains bar
bazic
bazic isnt special
foobar
foobar contains foo

这是基本的Bourne Shell功能。它不需要任何外部程序,也不需要特定于bash的程序,也不需要Posix。因此它应该是非常便携的。

简短的答案是否定的,不是如果您尝试使用vanilla sh,而无需bash扩展。在许多现代系统上,/bin/sh实际上是指向/bin/bash的链接,该链接提供了sh的功能(大部分)的超集。您的最初尝试将与Bash的内置[[扩展测试命令:http://mywiki.wooledege.org/bashfaq/031

最新更新