bash Linux命令进行通配符匹配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1953544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Linux command to do wild card matching
提问by GetFree
Is there any bash command to do something similar to:
是否有任何 bash 命令可以执行类似以下操作:
if [[ $string =~ $pattern ]]
but that it works with simple wild cards (?,*) and not complex regular expressions ??
但它适用于简单的通配符 (?,*) 而不是复杂的正则表达式 ??
More info:
更多信息:
I have a config file (a sort of .ini-like file) where each line is composed of a wild card pattern and some other data.
For any given input string that my script receives, I have to find the first line in the config file where the wild card pattern matches the input string and then return the rest of the data in that line.
It's simple. I just need a way to match a string against wild card patterns and not RegExps since the patterns may contain dots, brackets, dashes, etc. and I don't want those to be interpreted as special characters.
我有一个配置文件(一种类似 .ini 的文件),其中每一行都由通配符模式和其他一些数据组成。
对于我的脚本接收的任何给定输入字符串,我必须在配置文件中找到通配符模式与输入字符串匹配的第一行,然后返回该行中的其余数据。
这很简单。我只需要一种将字符串与通配符模式而不是 RegExp 匹配的方法,因为模式可能包含点、方括号、破折号等,我不希望这些被解释为特殊字符。
回答by Gordon Davisson
The [ -z ${string/$pattern} ]trick has some pretty serious problems: if string is blank, it'll match all possible patterns; if it contains spaces, the test command will parse it as part of an expression (try string="x -o 1 -eq 1"for amusement). bash's [[ expressions do glob-style wildcard matching natively with the == operator, so there's no need for all these elaborate (and trouble-prone) tricks. Just use:
这个[ -z ${string/$pattern} ]技巧有一些非常严重的问题:如果字符串为空,它将匹配所有可能的模式;如果它包含空格,则测试命令会将其解析为表达式的一部分(尝试string="x -o 1 -eq 1"娱乐一下)。bash 的 [[ 表达式使用 == 运算符在本地进行全局样式的通配符匹配,因此不需要所有这些精心设计(并且容易出错)的技巧。只需使用:
if [[ $string == $pattern ]]
回答by ?aphink
There's several ways of doing this.
有几种方法可以做到这一点。
In bash >= 3, you have regex matching like you describe, e.g.
在 bash >= 3 中,您有像您描述的正则表达式匹配,例如
$ foo=foobar
$ if [[ $foo =~ f.ob.r ]]; then echo "ok"; fi
ok
Note that this syntax uses regex patterns, so it uses .instead of ?to match a single character.
请注意,此语法使用正则表达式模式,因此它使用.代替?来匹配单个字符。
If what you want to do is just test that the string contains a substring, there's more classic ways of doing that, e.g.
如果您想要做的只是测试字符串是否包含子字符串,那么还有更经典的方法可以做到这一点,例如
# ${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
You can also test if a string begins or ends with an expression this way:
您还可以通过以下方式测试字符串是否以表达式开头或结尾:
# ${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
See the Parameter Expansionparagraph of man bashfor more info on these syntaxes. Using ##or %%instead of #and %respectively will achieve a longest matching instead of a simple matching.
有关这些语法的更多信息,请参阅man bash的参数扩展段落。分别使用or代替and将实现最长匹配而不是简单匹配。##%%#%
Another very classic way of dealing with wildcards is to use case:
处理通配符的另一种非常经典的方法是用例:
case $foo in
*bar)
echo "Foo matches *bar"
;;
bar?)
echo "Foo matches bar?"
;;
*)
echo "Foo didn't match any known rule"
;;
esac
回答by quack quixote
John T's answer was deleted, but I actually think he was on the right track. Here it is:
John T 的回答被删除了,但我实际上认为他是在正确的轨道上。这里是:
Another portable method which will work in most versions of bash is to echo your string then pipe to grep. If no match is found, it will evaluate to false as the result will be blank. If something is returned, it will evaluate to true.
[john@awesome]$string="Hello World" [john@awesome]$if [[ `echo $string | grep Hello` ]];then echo "match";fi match
另一种适用于大多数 bash 版本的便携式方法是回显您的字符串,然后通过管道传输到 grep。如果未找到匹配项,它将评估为 false,因为结果将为空白。如果返回某些内容,它将评估为真。
[john@awesome]$string="Hello World" [john@awesome]$if [[ `echo $string | grep Hello` ]];then echo "match";fi match
What John didn't consider is the wildcard requested by the answer. For that, use egrep, a.k.a. grep -E, anduse the regex wildcard .*. Here, .is the wildcard, and *is a multiplier meaning "any number of these". So, John's example becomes:
John 没有考虑的是答案要求的通配符。为此,使用egrep,又名grep -E,并使用正则表达式通配符.*。这里,.是通配符,*是一个乘数,意思是“这些中的任意数量”。所以,约翰的例子变成了:
$ string="Hello World"
$ if [[ `echo $string | egrep "Hel.*"` ]]; then echo "match"; fi
The .wildcard notation is fairly standard regex, so it should work with any command that speaks regex's.
该.通配符符号是相当标准的正则表达式,所以它应该与正则表达式讲的任何命令工作。
It does get nasty if you need to escape the special characters, so this may be sub-optimal:
如果您需要转义特殊字符,它确实会变得令人讨厌,因此这可能不是最佳选择:
$ if [[ `echo $string | egrep "\.\-$.*"` ]]; then echo "match"; fi

