在学习Shell脚本、 Linux 命令行,甚至是vim时,我们会接触到两个非常相似的概念,正则表达式和通配符。
什么时候使用通配符,什么时候使用正则表达式呢?这个问题我们可以查询使用文档来解决,例如 通过man find
查看 find
命令的使用手册,我们可以知道 -name pattern
使用的是通配符,而 -regex pattern
使用的却是正则表达式。
通配符的元字符
那么什么是通配符呢?通配符的元字符如下
*
星号用来匹配0个或多个字符。?
问号用来匹配任意一个字符。[]
匹配一个范围字符集内的一个字符。\
移除所有特殊字符的意义。例如\*
只匹配星号。
对于[]
有一点需要注意,[a-dx-z]
可能会表示abcdxyz
范围,也可能会表示aBbCcDdxYyZz
,这与地区排序规则有关,有的地区是使用C语言的排序规则的,也就是ASCII码顺序,有的地区使用字典排序规则,例如AaBbCcDd...
。
通常我们想让[a-dx-z]
翻译为abcdxyz
,我们可以设置环境变量LC_COLLATE
(指排序规则)或LC_ALL
(覆盖所有以LC_
开头的环境变量)值为C
。
另外,POSIX 标准增加一个字符类,来表示字符集,从而解决了[a-dx-z]
表示字符范围可能不一致的问题,例如[[:alnum:]]
表示字母和数字,[[:alpha:]]
表示字母,[[:digit:]]
表示数字,[[:lower:]]
表示小写字母,[[:upper:]]
表示大写字母,[[:word:]]
表示字母,数字,下划线。
我们来举几个通配符的例子,首先是 find
命令,如下
find . -name "*.java"
-name
后面使用的是通配符,注意点号.
不是通配符的特殊字符,因此它按照原义匹配。这个find
命令的意思是,在当前目录下,查找所有以.java
结尾的文件,并打印出来。
shell脚本中也有使用通配符的地方,例如
#!/bin/bash
file=foo.bar
if [[ $file == foo.* ]]; then
echo "Yes"
fi
使用通配符的时机
其实除了查看文档,我们也可以猜测什么时候使用通配符。
如果我们需要匹配文件/目录的名子或路径时,往往就是使用通配的地方。
参考
https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching