是否有任何bash命令可以执行类似的操作:
if [[ $string =~ $pattern ]]
但它适用于简单的通配符(?,*)而不是复杂的正则表达式?
更多信息:
我有一个配置文件(一种类似.ini的文件),其中每一行都由一个通配符模式和一些其他数据组成。
对于我的脚本接收的任何给定输入字符串,我必须在配置文件中找到通配符模式与输入字符串匹配的第一行,然后返回该行中的其余数据。
这很简单。我只需要一种方法来匹配一个字符串与外卡模式而不是RegExps,因为模式可能包含点,括号,破折号等,我不希望这些被解释为特殊字符。
答案 0 :(得分:3)
[ -z ${string/$pattern} ]
技巧有一些非常严重的问题:如果字符串为空白,它将匹配所有可能的模式;如果它包含空格,则test命令会将其解析为表达式的一部分(尝试string="x -o 1 -eq 1"
进行娱乐)。 bash的[[表达式本身与==运算符进行glob样式的通配符匹配,因此不需要所有这些精心设计(并且容易出错)的技巧。只需使用:
if [[ $string == $pattern ]]
答案 1 :(得分:2)
有几种方法可以做到这一点。
在bash> = 3中,您就像您描述的那样使用正则表达式匹配,例如:
$ foo=foobar
$ if [[ $foo =~ f.ob.r ]]; then echo "ok"; fi
ok
请注意,此语法使用正则表达式模式,因此它使用.
代替?
来匹配单个字符。
如果您想要做的只是测试字符串是否包含子字符串,那么有更经典的方法,例如。
# ${foo/b?r/} replaces "b?r" with the empty string in $foo
# So we're testing if $foo does not contain "b?r" one time
$ if [[ ${foo/b?r/} = $foo ]]; then echo "ok"; fi
您还可以通过以下方式测试字符串是否以表达式开头或结尾:
# ${foo%b?r} removes "bar" in the end of $foo
# So we're testing if $foo does not end with "b?r"
$ if [[ ${foo%b?r} = $foo ]]; then echo "ok"; fi
# ${foo#b?r} removes "b?r" in the beginning of $foo
# So we're testing if $foo does not begin with "b?r"
$ if [[ ${foo#b?r} = $foo ]]; then echo "ok"; fi
ok
有关这些语法的详细信息,请参阅man bash的参数扩展段落。分别使用##
或%%
代替#
和%
将实现最长匹配,而不是简单匹配。
处理通配符的另一种非常经典的方法是使用大小写:
case $foo in
*bar)
echo "Foo matches *bar"
;;
bar?)
echo "Foo matches bar?"
;;
*)
echo "Foo didn't match any known rule"
;;
esac
答案 2 :(得分:0)
John T的回答被删除了,但我实际上认为他是在正确的轨道上。这是:
另一种适用于大多数bash版本的便携式方法是 回显你的字符串然后管道到grep。如果找不到匹配,则会 评估为false,因为结果将为空。如果有东西归还, 它会评估为真。
[john@awesome]$string="Hello World" [john@awesome]$if [[ `echo $string | grep Hello` ]];then echo "match";fi match
John没有考虑的是答案所要求的通配符。为此,请使用egrep
,a.k.a。grep -E
,和使用正则表达式通配符.*
。这里,.
是通配符,*
是一个乘数,意思是“任意数量的这些”。所以,John的例子变成了:
$ string="Hello World"
$ if [[ `echo $string | egrep "Hel.*"` ]]; then echo "match"; fi
.
通配符表示法是相当标准的正则表达式,所以它应该适用于任何说正则表达式的命令。
如果你需要转义特殊字符,它确实很讨厌,所以这可能是次优的:
$ if [[ `echo $string | egrep "\.\-\$.*"` ]]; then echo "match"; fi