正则表达式(regular expression)一般简写为 regex 或 re,是一种指定字符串模式的简洁方式。git
图 20-一、20-二、20-3汇总了正则表达式的使用语法。正则表达式
正则表达式是一种指定字符模式的简洁方式。在正则表达式中,普通字符匹配自身,特定的元字符拥有特殊的含义。本表列举了用来执行基本模式匹配的元字符。shell
在正则表达式中,下述元字符称为重复运算符,能够用来匹配多个指定字符的实例。express
注意:一些程序不支持{,m},由于{,m}不是标准的。学习
正则表达式中能够包含有定义一组字符的字符类。为了方便起见,正则表达式中有一组预约义字符类,能够将这些预约义字符类用做字符集合的缩写。本表示范了最重要的预约义字符类。注意方括号和冒号都是名称的一部分。spa
最右边的一列给出了与预约义字符类等价的字符范围。若是系统使用的是 C 排序序列,则能够使用这些范围取代类的名称。为了确保系统使用的是 C 排序序列,能够将环境变量 LC_COLLATE 的值设置为 C。code
Unix支持两种主要的正则表达式变体:一个现代版本,一个之前的废弃版本。现代版本的正则表达式是扩展正则表达式(extended regular expression),或者简称为 ERE。它是当前的标准,疏于 IEEE 1003.2 标准(POSIX 的一部分)。排序
之前版本的正则表达式是基本正则表达式(basic regular expression),或者简称为 BRE。因其功能弱,语法容易混淆,已废弃。但仍然有时候不得不选择使用基本正则表达式。(例如,sed 只支持 BRE)字符串
使用扩展正则表达式:grep -E 或 egrepit
图 20-4,列举了基本正则表达式的限制,供参考
假定有一个文件 data,考虑如下用法:
grep '^Harley' data
grep 'Harley$' data
grep '^Harley$' data
grep '^$' data | wc -l
grep '\<kn' data
grep 'ow\>' data
grep '\<know\>' data
下述3条命令都是等价的:
grep -w 'cat' data
grep '\<cat\>' data
grep '\bcat\b' data
假定有一个文件 data,考虑如下用法:
grep 'Har..y' data
grep 'H[aA]' data
grep 'li[cs]en[cs]e' data
grep '\<li[cs]en[cs]e\>' data
有一些字符集是比较常见的,所以他们被冠以相应的名称,从而方便使用。这些字符集称为预约义字符类。
预约义字符类的使用比较直接,除了一个规则以外,这个规则是:方括号其实是名称的一部分。由于,当时用预约义字符类时,必须包含第二组方括号,以维持正确的语法(当使用字符类时,外面的方括号不属于类)。
grep '21[[:alpha:]]' data
grep '[[:upper:]][[:upper:]][[:digit:]][[:lower:]]' data
grep '[3-7]' data
grep 'X[0-9][0-9]' data grep 'X[[:digit:]][[:digit:]]' data
grep 'X[^ao]' data
grep '[^A-Za-z]' data
grep '[^[:alpha:]]' data
此处不单独阐述。为了将字典排序序列改变成 C 排序序列,提示如下命令:
export LC_COLLATE=C
export LC_COLLATE=POSIX
setenv LC_COLLATE C
setenv LC_COLLATE POSIX
locale
locale -a
考虑如下命令:
grep 'H[[:lower:]]' data
grep 'H[a-z]' data
grep '[A-Za-z][0-9][a-z]' data
grep '[[:alpha:]][[:digit:]][[:lower:]]' data
grep '[A-Z][0-9][A-Z] [0-9][A-Z][0-9]'
data grep '[[:upper:]][[:digit:]][[:upper:]] [[:digit:]][[: upper:]][[:digit:]]' data
选择使用哪种类型的字符类——是范围仍是预约义名称——由本身决定。许多之前的 Unix 用户倾向于使用范围,由于他们学习得就是范围。此外,范围还比名称更容易键入。
可是,名称更可读,从而使得它们更适合在 shell 脚本中使用。另外,无论使用哪种区域设置或语言,名称老是正确的,所以它们的移植性更出色。例如,假设处理的文本中包含非英语字符,如 é(有重音符的 e)。经过使用 [:lower:],就能够确保获取 é。可是,若是使用a-z的话,可能实现不了这种效果。
考虑如下命令:
grep 'H[a-z]*' data
grep 'H[[:lower:]]*' data
grep 'error.*code' data
grep ':.*:' data
grep 'variable[0-9]+' data
grep 'variable[[:digit:]]+' data
grep '[vV]ariable[0-9]+' data
grep 'colou?r' data
grep '\<[0-9]{2,3}\>' data
grep 'cat|dog|bird|hamster' data
grep '\<(cat|dog|bird|hamster)\>' data
grep '\$' data
grep '\\\*.*[A-Za-z]+\$' data
字典文件常见位置:
/usr/share/dict/words
/usr/dict/words
/usr/share/lib/dict/words
1. 哪些英语单词以“qu”开头并以“y”结尾?
grep '^qu[a-z]+y$' /usr/share/dict/words
2. 查找一个包含全部 5 个元音字母 a、e、i、o、u(而且以该顺序出现)的普通英语单词。这 5 个字母没必要连在一块儿,可是它们必须按字母表顺序出现。
grep 'a[a-z]*e[a-z]*i[a-z]*o[a-z]*u' /usr/share/dict/words
3. 查找全部两个字母长的 Unix 命令
ls /bin | grep '^[a-z]{2}$'
ls /bin | egrep '^[a-z]{2}$'
ls /bin | grep '^[a-z][a-z]$'
ls /usr/bin | grep '^[a-z]{2}$'
ls /bin | grep -c '^[a-z]{2}$'
ls /usr/bin | grep -c '^[a-z]{2}$'
每当键入以文件名做为参数的命令时,能够经过使用特定的元字符——通配符(wildcard)——指定多个文件名。元字符是由shell 解释时拥有特殊含义的字符。当在文件名中使用通配符时,通配符就拥有特殊的含义。
乍一看,通配符和正则表达式元字符及其类似。实际上,通配符更加简单一些。此外,它们只有一个用途:当键入一条命令时匹配一组文件名。
图 24-5 列出了基本的通配符及其含义。注意:当键入路径名时,不能匹配 / 字符,该字符必须显示键入。
根据所使用的 shell 的类型不一样,使用通配符指定文件的正式称呼也有所不一样。在 Bash 中,称之为路径名扩展(pathname expansion);在 Korn shell 中,称之为文件名生成(filename generation);在 C-Shell 或 Tcsh 中,称之为文件名替换(filename substitution)。当 shell 执行实际替换时,称之为通配(globbing)
通配符能够使用范围匹配指定字符集中的字符。最多见的包括 [a-z] 匹配小写字母,[A-Z] 匹配大写字母。这类范围适用于 C 区域设置,而不适用于 en-US 区域设置。做为备选方法,能够使用预约义字符类替代范围。图 24-6 中列举了一些最重要的预约义字符类。
一些例子:
ls h*
ls /bin/[a-z][a-z] /usr/bin/[a-z][a-z]
ls /bin/[[:lower:]][[:lower:]] /usr/bin/[[:lower:]][[:lower:]]
ls /home/{harley,weedly,tln}
cat olddata1 olddata2 olddata3 newdata1 newdata2 newdata3 > master
cat {old,new}data{1,2,3} > master
cat {old,new}data[1-3] > master
mkdir ~/work/essays ~/work/photos ~/work/bin ~/work/music
mkdir ~/work/{essays,photos,bin,music}
touch data{old,new,backup,master,final}
正如前面所述,当 shell 匹配通配符时,在参数传递给程序以前,通配符已变成实际文件名。若是使用的模式不匹配任何文件,那么 shell 将显示一个适当的消息。
如下是一些例子:
ls -F /etc | grep -c "/"
grep -i pizza food-costs
grep -in pizza food-costs
grep -l Harley names oldnames newnames
grep -L Harley names oldnames newnames
grep -w now memo
grep -v DONE homework
grep -cv DONE homework
grep -x Harley names
grep -r initialize admin
grep -rs / 'shutdown now'