有不止一种正则表达式。它通过正则表达式引擎(regular expression engin)实现的。

在 Linux 中,有两种流行的正则表达式引擎:

  • POSIX 基础正则表达式(basic regular expression,BRE)引擎;
  • POSIX 扩展正则表达式(extended regular expression,ERE)引擎;

sed 编辑器只符合 BRE 引擎。gawk 支持 ERE 引擎。

基础正则表达式

点号和字符组

点号:匹配除换行符之外的任意单个字符。

字符组(character class):匹配方括号里面的任意一个字符,比如 [ch]

排除型字符组:在字符组里面添加 ^,比如 [^ch]

  1. $ cat data6
  2. This is a test of a line.
  3. The cat is sleeping.
  4. That is a very nice hat.
  5. This test is at line four.
  6. at ten o'clock.
  7. # 注意最后一行没有匹配上,因为 at 前面的换行符不能匹配点号
  8. $ sed -n '/.at/p' data6
  9. The cat is sleeping.
  10. That is a very nice hat.
  11. This test is at line four.
  12. # 匹配 cat 或 hat
  13. $ sed -n '/[ch]at/p' data6
  14. The cat is sleeping.
  15. That is a very nice hat.
  16. # 匹配除了 cat 或 hat 之外的字符
  17. $ sed -n '/[^ch]at/p' data6
  18. This test is at line four.
  19. # 多个字符组一起使用
  20. $ echo "Yes" | sed -n '/[Yy][Ee][Ss]/p'
  21. Yes
  22. # 但也会匹配这个
  23. $ echo "Yess" | sed -n '/[Yy][Ee][Ss]/p'
  24. Yess
  25. # 优化,加上行首和行尾的限制
  26. $ echo "Yess" | sed -n '/^[Yy][Ee][Ss]$/p'

区间

比如 [0-9] 匹配数字 0~9,相当于 [0123456789]

[a-h] 匹配字母 a~h。

还可以指定多个不连续区别,比如 [a-ch-m],匹配 a~c 和 g~m 中的字母。

特殊字符组

BRE 还包含了一些特殊的字符组:

描述
[[:alpha:]] 匹配任意字母,不管是大写还是小写
[[:alnum:]] 匹配任意字母和数字
[[:blank:]] 匹配空格或制表符
[[:digit:]] 匹配0~9之间的数字
[[:lower:]] 匹配小写字母
[[:print:]] 匹配可打印字符
[[:punct:]] 匹配标点符号
[[:space:]] 匹配任意空白字符:空格、制表符、NL、FF、VT和CR
[[:upper:]] 匹配大写字母
  1. $ echo "abc" | sed -n '/[[:digit:]]/p'
  2. $ echo "abc" | sed -n '/[[:alnum:]]/p'
  3. abc
  4. # 匹配标点符号
  5. $ echo "This is a test" | sed -n '/[[:punct:]]/p'
  6. $ echo "This is, a test" | sed -n '/[[:punct:]]/p'
  7. This is, a test

星号

星号匹配它前面的字符 0 次或多次。

  1. echo "ik" | sed -n '/ie*k/p'
  2. ik
  3. $ echo "iek" | sed -n '/ie*k/p'
  4. iek
  5. $ echo "ieek" | sed -n '/ie*k/p'
  6. ieek

星号和点号一起使用,匹配任意数量的任意字符。

  1. $ echo "This is a regular pattern expression" | sed -n '/regular.*expression/p'
  2. This is a regular pattern expression

星号和字符组一起使用:

  1. echo "bt" | sed -n "/b[ae]*t/p"
  2. bt
  3. $ echo "bat" | sed -n "/b[ae]*t/p"
  4. bat
  5. $ echo "baaaeeet" | sed -n "/b[ae]*t/p"
  6. baaaeeet

扩展正则表达式

POSIX ERE 模式包括了一些可供 Linux 应用和工具使用的额外符号。gawk 能够识别 ERE 模式,但 sed 编辑器不能。

问号

问号匹配前面的字符 0 次或 1 次。

  1. echo "bt" | gawk '/be?t/{print $0}'
  2. bt
  3. $ echo "bet" | gawk '/be?t/{print $0}'
  4. bet
  5. $ echo "beet" | gawk '/be?t/{print $0}'
  6. $

和字符组结合使用:

  1. echo "bet" | gawk '/b[ae]?t/{print $0}'
  2. bet
  3. $ echo "bat" | gawk '/b[ae]?t/{print $0}'
  4. bat
  5. $ echo "baet" | gawk '/b[ae]?t/{print $0}'
  6. $

加号

加号匹配前面的字符 1 次或多次。

  1. $ echo "bet" | gawk '/be+t/{print $0}'
  2. bet
  3. $ echo "beeet" | gawk '/be+t/{print $0}'
  4. beeet
  5. $ echo "bt" | gawk '/be+t/{print $0}'
  6. $

和字符组结合使用:

  1. $ echo "bat" | gawk '/b[ae]+t/{print $0}'
  2. bat
  3. $ echo "baet" | gawk '/b[ae]+t/{print $0}'
  4. baet
  5. $ echo "bt" | gawk '/b[ae]+t/{print $0}'
  6. $

花括号

{m} 匹配字符 m 次;

{m, n} 匹配字符至少 m 次,至多 n 次。

  1. $ echo "bt" | gawk '/be{1}t/{print $0}'
  2. $ echo "bet" | gawk '/be{1}t/{print $0}'
  3. bet
  4. $ echo "beet" | gawk '/be{1}t/{print $0}'
  5. $ echo "beet" | gawk '/be{1,2}t/{print $0}'
  6. beet

管道符号

逻辑或方式匹配字符,其中一个匹配就可以。

  1. $ echo "The cat is asleep" | gawk '/dog|cat/{print $0}'
  2. The cat is asleep

表达式分组

  1. $ echo "Sat" | gawk '/Sat(urday)?/{print $0}'
  2. Sat
  3. $ echo "Saturday" | gawk '/Sat(urday)?/{print $0}'
  4. Saturday
  5. $ echo "cat" | gawk '/(c|a)a(b|t)/{print $0}'
  6. cat

实战

下面的例子计算环境变量 PATH 中定义的目录里的可执行文件的数量。

  1. $ echo $PATH | sed 's/:/ /g'
  2. /home/xiaocan/gems/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games
  3. $ cat countfiles
  4. #!/bin/bash
  5. # count number of files in your PATH
  6. mypath=$(echo $PATH | sed 's/:/ /g')
  7. count=0
  8. for path in $mypath
  9. do
  10. check=$(ls $path)
  11. for item in $check
  12. do
  13. count=$(($count+1))
  14. done
  15. echo "$path - $count"
  16. count=0
  17. done
  18. $ sh countfiles
  19. /home/xiaocan/gems/bin - 7
  20. /usr/local/sbin - 0
  21. /usr/local/bin - 6
  22. /usr/sbin - 237
  23. /usr/bin - 1699
  24. /sbin - 273
  25. /bin - 176
  26. /usr/games - 1
  27. /usr/local/games - 0