Linux命令做外卡匹配

时间:2009-12-23 08:35:39

标签: linux bash shell wildcard

是否有任何bash命令可以执行类似的操作:

if [[ $string =~ $pattern ]]

但它适用于简单的通配符(?,*)而不是复杂的正则表达式?


更多信息:

我有一个配置文件(一种类似.ini的文件),其中每一行都由一个通配符模式和一些其他数据组成。
对于我的脚本接收的任何给定输入字符串,我必须在配置文件中找到通配符模式与输入字符串匹配的第一行,然后返回该行中的其余数据。
这很简单。我只需要一种方法来匹配一个字符串与外卡模式而不是RegExps,因为模式可能包含点,括号,破折号等,我不希望这些被解释为特殊字符。

3 个答案:

答案 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