正则表达式

1. 综述

正则表达式(regular expression)一般简写为 regex 或 re,是一种指定字符串模式的简洁方式。git

图 20-一、20-二、20-3汇总了正则表达式的使用语法。正则表达式

正则表达式是一种指定字符模式的简洁方式。在正则表达式中,普通字符匹配自身,特定的元字符拥有特殊的含义。本表列举了用来执行基本模式匹配的元字符。shell

在正则表达式中,下述元字符称为重复运算符,能够用来匹配多个指定字符的实例。express

注意:一些程序不支持{,m},由于{,m}不是标准的。学习

正则表达式中能够包含有定义一组字符的字符类。为了方便起见,正则表达式中有一组预约义字符类,能够将这些预约义字符类用做字符集合的缩写。本表示范了最重要的预约义字符类。注意方括号和冒号都是名称的一部分。spa

最右边的一列给出了与预约义字符类等价的字符范围。若是系统使用的是 C 排序序列,则能够使用这些范围取代类的名称。为了确保系统使用的是 C 排序序列,能够将环境变量 LC_COLLATE 的值设置为 C。code

2. 基本和扩展正则表达式

Unix支持两种主要的正则表达式变体:一个现代版本,一个之前的废弃版本。现代版本的正则表达式是扩展正则表达式(extended regular expression),或者简称为 ERE。它是当前的标准,疏于 IEEE 1003.2 标准(POSIX 的一部分)。排序

之前版本的正则表达式是基本正则表达式(basic regular expression),或者简称为 BRE。因其功能弱,语法容易混淆,已废弃。但仍然有时候不得不选择使用基本正则表达式。(例如,sed 只支持 BRE字符串

使用扩展正则表达式:grep -E 或 egrepit

图 20-4,列举了基本正则表达式的限制,供参考

3. 匹配单词和行

假定有一个文件 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

4. 匹配字符:字符类

假定有一个文件 data,考虑如下用法:

  • grep 'Har..y' data

  • grep 'H[aA]' data

  • grep 'li[cs]en[cs]e' data

  • grep '\<li[cs]en[cs]e\>' data

5. 预约义字符类:范围

有一些字符集是比较常见的,所以他们被冠以相应的名称,从而方便使用。这些字符集称为预约义字符类

预约义字符类的使用比较直接,除了一个规则以外,这个规则是:方括号其实是名称的一部分。由于,当时用预约义字符类时,必须包含第二组方括号,以维持正确的语法(当使用字符类时,外面的方括号不属于类)。

  • 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

6. 区域设置和排序序列

此处不单独阐述。为了将字典排序序列改变成 C 排序序列,提示如下命令:

  • export LC_COLLATE=C

  • export LC_COLLATE=POSIX

  • setenv LC_COLLATE C

  • setenv LC_COLLATE POSIX

  • locale

  • locale -a

7. 使用范围和预约义字符类

考虑如下命令:

  • 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的话,可能实现不了这种效果。

8. 重复运算符

考虑如下命令:

  • 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

10. 解决3个有趣的难题

字典文件常见位置:

  • /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}$' 

附录1. 通配符

每当键入以文件名做为参数的命令时,能够经过使用特定的元字符——通配符(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 将显示一个适当的消息。

附录2. grep 重要的选项

如下是一些例子:

  • 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'

附录3. 补充

  • \s:匹配任意的空白符
  • \S:匹配任意不是空白符的字符
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息