How do you tell if a string contains another string in POSIX sh?
本问题已经有最佳答案,请猛点这里访问。
我想编写一个unix shell脚本,如果另一个字符串中有一个字符串,它将执行各种逻辑。例如,如果我在某个文件夹中,请关闭分支。有人能告诉我怎么做吗?如果可能的话,我想让它不特定于shell(也就是说,不只是bash),但是如果没有其他方法,我可以用它来做。
1 2 3 4 5 6 7 8 9 10 11 | #!/usr/bin/env sh if ["$PWD" contains"String1" ] then echo"String1 present" elif ["$PWD" contains"String2" ] then echo"String2 present" else echo"Else" fi |
这里还有另一个解决方案。它使用了posix子字符串参数扩展,所以可以在bash、dash、ksh中使用。
1 | test"${string#*$word}" !="$string" && echo"$word found in $string" |
编辑:这是个好主意,C.罗斯。下面是一个功能化版本,其中包含一些示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # contains(string, substring) # # Returns 0 if the specified string contains the specified substring, # otherwise returns 1. contains() { string="$1" substring="$2" if test"${string#*$substring}" !="$string" then return 0 # $substring is in $string else return 1 # $substring is not in $string fi } contains"abcd""e" || echo"abcd does not contain e" contains"abcd""ab" && echo"abcd contains ab" contains"abcd""bc" && echo"abcd contains bc" contains"abcd""cd" && echo"abcd contains cd" contains"abcd""abcd" && echo"abcd contains abcd" contains"""" && echo"empty string contains empty string" contains"a""" && echo"a contains empty string" contains"""a" || echo"empty string does not contain a" contains"abcd efgh""cd ef" && echo"abcd efgh contains cd ef" contains"abcd efgh""" && echo"abcd efgh contains a space" |
纯POSIX外壳:
1 2 3 4 5 6 7 8 | #!/bin/sh CURRENT_DIR=`pwd` case"$CURRENT_DIR" in *String1*) echo"String1 present" ;; *String2*) echo"String2 present" ;; *) echo"else" ;; esac |
像ksh或bash这样的扩展shell具有奇特的匹配机制,但是旧式的
遗憾的是,我不知道在sh中实现这一点的方法。但是,使用bash(从3.0.0版开始,这可能是您所拥有的版本),您可以使用如下的=~操作符:
1 2 3 4 5 6 7 8 9 10 11 12 | #!/bin/bash CURRENT_DIR=`pwd` if [["$CURRENT_DIR" =~"String1" ]] then echo"String1 present" elif [["$CURRENT_DIR" =~"String2" ]] then echo"String2 present" else echo"Else" fi |
作为额外的奖励(和/或警告,如果字符串中有任何有趣的字符),=~如果省略引号,则接受regex作为正确的操作数。
1 2 3 4 5 6 7 8 9 10 11 12 | #!/usr/bin/env sh # Searches a subset string in a string: # 1st arg:reference string # 2nd arg:subset string to be matched if echo"$1" | grep -q"$2" then echo"$2 is in $1" else echo"$2 is not in $1" fi |
这里有一个链接,指向您的问题的各种解决方案。
这是我最喜欢的,因为它让人最容易理解:
星型通配符方法
1 2 3 4 | if [["$string" == *"$substring"* ]]; then return 1 fi return 0 |
1 2 3 4 5 6 | case $(pwd) in *path) echo"ends with path";; path*) echo"starts with path";; *path*) echo"contains path";; *) echo"this is the default";; esac |
有bash regexps。或者有‘expr’:
1 2 3 4 5 | if expr"$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname"$PRG"`/"$link" fi |
在某些特殊情况下,如果您希望查找某个单词是否包含在长文本中,可以使用循环对长文本进行迭代。
1 2 3 4 5 6 7 8 9 | found=F query_word=this long_string="many many words in this text" for w in $long_string; do if ["$w" ="$query_word" ]; then found=T break fi done |
这是纯伯恩贝壳。
请参见"测试"程序的手册页。如果您只是测试目录的存在性,那么通常会这样做:
1 2 3 | if test -d"String1"; then echo"String1 present" end |
如果您实际尝试匹配字符串,也可以使用bash扩展规则和通配符:
1 2 3 | if test -d"String*"; then echo"A directory starting with 'String' is present" end |
如果你需要做一些更复杂的事情,你需要使用另一个程序,比如expr。
如果你想要一个只有ksh的方法,它和"test"一样快,你可以做如下的事情:
1 2 3 4 5 6 7 8 | contains() # haystack needle { haystack=${1/$2/} if [ ${#haystack} -ne ${#1} ] ; then return 1 fi return 0 } |
它的工作原理是删除草垛中的针,然后比较新旧草垛的串长。
1 | test $(echo"stringcontain""ingcon" |awk '{ print index($1, $2) }') -gt 0 && echo"String 1 contain string 2" |
-->output:字符串1包含字符串2