如何判断一个字符串是不是包含 POSIX sh 中的另一个字符串?
Posted
技术标签:
【中文标题】如何判断一个字符串是不是包含 POSIX sh 中的另一个字符串?【英文标题】:How do you tell if a string contains another string in POSIX sh?如何判断一个字符串是否包含 POSIX sh 中的另一个字符串? 【发布时间】:2011-02-19 06:03:54 【问题描述】:我想编写一个 Unix shell 脚本,如果另一个字符串中有一个字符串,它将执行各种逻辑。例如,如果我在某个文件夹中,请分支。有人可以告诉我如何做到这一点吗?如果可能的话,我想让它不是特定于 shell 的(即不仅仅是 bash),但如果没有其他方法我可以做到这一点。
#!/usr/bin/env sh
if [ "$PWD" contains "String1" ]
then
echo "String1 present"
elif [ "$PWD" contains "String2" ]
then
echo "String2 present"
else
echo "Else"
fi
【问题讨论】:
我知道这已经过时了,但这里有一些事情要留给以后的访问者注意: (1) 为环境和 shell 内部变量保留 SNAKE_CASE 变量名通常是一种很好的做法。 (2)设置CURRENT_DIR
是多余的;你可以使用$PWD
。
【参考方案1】:
这是另一个解决方案。这使用POSIX substring parameter expansion,所以它适用于 Bash、Dash、KornShell (ksh)、Z shell (zsh) 等。
test "$string#*$word" != "$string" && echo "$word found in $string"
带有一些示例的功能化版本:
# 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"
【讨论】:
如果子字符串包含反斜杠,这对我不起作用。像往常一样,substring="$( printf '%q' "$2" )"
拯救了这一天。
这也匹配了错误的子字符串。 string = "aplha beta betaone" substring="beta" 。它同时匹配 betaone 和 dbeta,我认为这是错误的。
using wildcards 怎么样? [[ $haystack == *"My needle"* ]]
问题是双括号不是 POSIX,这是问题的前提,@Pablo。
这不适用于[]
等特殊字符。看我的回答***.com/a/54490453/712666。【参考方案2】:
有Bash regular expressions。或者有'expr':
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
【讨论】:
【参考方案3】:在特殊情况下,如果要查找某个单词是否包含在长文本中,可以使用循环遍历长文本。
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
这是纯 Bourne shell。
【讨论】:
【参考方案4】:请参阅“测试”程序的手册页。 如果您只是测试目录是否存在,您通常会执行以下操作:
if test -d "String1"; then
echo "String1 present"
end
如果你真的想匹配一个字符串,你也可以使用 bash 扩展规则和通配符:
if test -d "String*"; then
echo "A directory starting with 'String' is present"
end
如果你需要做一些更复杂的事情,你需要使用另一个程序,比如 expr。
【讨论】:
您的第二个示例中似乎有一个虚假的双引号 (")。【参考方案5】:#!/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
【讨论】:
将grep -q "$2"
更改为 grep -q "$2" > /dev/null
以避免不希望的输出。
将 grep -q "$2"
更改为 grep -q "$2" 2>/dev/null
以避免不希望的输出。
grep
不是 POSIX。
@AdelM。你确定吗? unix.com/man-page/posix/1p/grep
@TrippKinetics。我误解了。你是对的。【参考方案6】:
这里是link,可以解决您的问题的各种解决方案。
这是我最喜欢的,因为它具有最人性化的可读性:
星号通配符方法
if [[ "$string" == *"$substring"* ]]; then
return 1
fi
return 0
【讨论】:
在sh
我收到了“未知操作数”。不过适用于 Bash。
[[
不是 POSIX
这适用于 IBM z/OS USS POSIX shell。【参考方案7】:
遗憾的是,我不知道在 sh.但是,使用 bash(从 3.0.0 版本开始,这可能是您所拥有的),您可以像这样使用 =~ 运算符:
#!/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
作为额外的奖励(和/或警告,如果您的字符串中有任何有趣的字符),如果您省略引号,=~ 接受正则表达式作为正确的操作数。
【讨论】:
不要引用正则表达式,否则它将不正常工作。例如,尝试[[ test =~ "test.*" ]]
与 [[ test =~ test.* ]]
。
好吧,如果您正在测试子字符串,它会正常工作,就像在原始问题中一样,但它不会将正确的操作数视为正则表达式。我会更新我的答案以使其更清楚。
这是 Bash,而不是问题所要求的 POSIX sh。【参考方案8】:
如果您想要一个与“测试”一样快的仅 ksh 方法,您可以执行以下操作:
contains() # haystack needle
haystack=$1/$2/
if [ $#haystack -ne $#1 ] ; then
return 1
fi
return 0
它的工作原理是删除干草堆中的针,然后比较新旧干草堆的字符串长度。
【讨论】:
不可以返回test
的结果吗?如return [ $#haystack -eq $#1 ]
?
是的,没错。我将这样保留它,因为对于外行来说更容易理解。如果您在代码中使用,请使用 @AlexisWilke 方法。【参考方案9】:
test $(echo "stringcontain" "ingcon" |awk ' print index($1, $2) ') -gt 0 && echo "String 1 contain string 2"
--> 输出:字符串 1 包含字符串 2
【讨论】:
【参考方案10】:case $(pwd) in
*path) echo "ends with path";;
path*) echo "starts with path";;
*path*) echo "contains path";;
*) echo "this is the default";;
esac
【讨论】:
【参考方案11】:纯 POSIX 外壳:
#!/bin/sh
CURRENT_DIR=`pwd`
case "$CURRENT_DIR" in
*String1*) echo "String1 present" ;;
*String2*) echo "String2 present" ;;
*) echo "else" ;;
esac
像 ksh 或 bash 这样的扩展 shell 有花哨的匹配机制,但旧式的 case
却出奇地强大。
【讨论】:
以上是关于如何判断一个字符串是不是包含 POSIX sh 中的另一个字符串?的主要内容,如果未能解决你的问题,请参考以下文章