目录
当前位置: 首页 > 文档资料 > Shell 中文文档 >

第19章. 正则表达式

优质
小牛编辑
133浏览
2023-12-01

为了充分发挥shell编程的威力,你需要精通正则表达式。 在脚本编程中的一些命令和软件包普遍使用正则表达式,例如grep, expr, sedawk.

点 --.-- 匹配除了新行符之外的任意一个字符.

美元符 --$-- 在正则表达式中匹配行尾.

"^$"匹配空行.

  • 方括号 --[...]-- 在正则表达式中表示匹配括号中的一个字符.

    "[xyz]"匹配字符x, y, 或z.

    "[c-n]"匹配从字符cn之间的任意一个字符.

    "[B-Pk-y]"匹配从BP或从ky的任意一个字符.

    "[a-z0-9]"匹配任意小写字母或数字.

    "[^b-d]"匹配除了从bd范围内所有的字符. 这是正则表达式中反转意思或取否的一个例子。(就好像在别的情形中!字符所扮演的角色).

    多个方括号字符集组合使用可以匹配一般的单词和数字模式。"[Yy][Ee][Ss]"匹配yes, Yes, YES, yEs, 等等. "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]"匹配社会安全码(Social Security number).

  • 反斜杠字符 --\-- 转义(escapes)一个特殊的字符,使这个字符表示原来字面上的意思.

    "\$"表示了原来的字面意思"$",而不是在正则表达式中表达的匹配行尾的意思.同样,"\\"也被解释成了字面上的意思"\".

  • 转义(escape)"尖角号"--\<...\>-- 用于表示单词的边界.

    尖角号必须被转义,因为不这样做的话它们就表示单纯的字面意思而已.

    "\<the\>"匹配单词"the",但不匹配"them", "there", "other", 等等.

     
    bash$ 
    
    
    cat textfile
    
     
    This is line 1, of which there is only one instance.
     This is the only instance of line 2.
     This is line 3, another line.
     This is line 4.

    bash$ grep 'the' textfileThis is line 1, of which there is only one instance.This is the only instance of line 2.This is line 3, another line.

    bash$ grep '\<the\>' textfileThis is the only instance of line 2.

确定正则表达式能否工作的唯一办法是测试它.

   1 TEST FILE: tstfile                          # 不匹配.
   2                                             # 不匹配.
   3 Run   grep "1133*"  on this file.           # 匹配.
   4                                             # 不匹配.
   5                                             # 不匹配.
   6 This line contains the number 113.          # 匹配.
   7 This line contains the number 13.           # 不匹配.
   8 This line contains the number 133.          # 不匹配.
   9 This line contains the number 1133.         # 匹配.
  10 This line contains the number 113312.       # 匹配.
  11 This line contains the number 1112.         # 不匹配.
  12 This line contains the number 113312312.    # 匹配.
  13 This line contains no numbers at all.       # 不匹配.
 
bash$ 


grep "1133*" tstfile

 
Run   grep "1133*"  on this file.           # 匹配.
 This line contains the number 113.          # 匹配.
 This line contains the number 1133.         # 匹配.
 This line contains the number 113312.       # 匹配.
 This line contains the number 113312312.    # 匹配.
 	      
    • 扩展的正则表达式. 增加了一些元字符到上面提到的基本的元字符集合里. 它们在egrep, awk,和Perl中使用.

    • 问号 --?-- 匹配零或一个前面的字符. 它一般用于匹配单个字符.

    • 加号 --+-- 匹配一个或多个前面的字符.它的作用和*很相似,但唯一的区别是它不匹配零个字符的情况.

         1 # GNU 版本的 sed 和 awk 可以使用"+",
         2 # 但它应该转义一下.
         3
         4 echo a111b | sed -ne '/a1\+b/p'
         5 echo a111b | grep 'a1\+b'
         6 echo a111b | gawk '/a1+b/'
         7 # 上面三句都是等价的效果.
         8
         9 # 多谢, S.C.
    • 转义"大括号"--\{ \}-- 指示前面正则表达式匹配的次数.

      要转义是因为不转义的话大括号只是表示他们字面上的意思。这个用法只是技巧上的而不是基本正则表达式的内容。

      "[0-9]\{5\}"精确匹配5个数字 (从 0 到 9的数字).

       

      大括号不能在“经典”(不是POSIX兼容)的正则表达式版本的awk中使用. 然而, gawk一个选项--re-interval来允许使用大括号(不必转义).

       
      bash$ 
      
      
      echo 2222 | gawk --re-interval '/2{3}/'
      
       
      2222
       	      

      Perl和一些egrep版本不要求转义大括号.

    • 竖线 -- |-- "或"正则操作符用于匹配一组可选的字符.

       
      bash$ 
      
      
      egrep 're(a|e)d' misc.txt
      
       
      People who read seem to be better informed than those who do not.
       The clarinet produces sound by the vibration of its reed.
       	      

 

一些sed, ed, 和ex的版本像GNU的软件版本一样支持上面描述的扩展正则表达式的版本。

POSIX字符类. [:class:]

这是另外一个可选的用于指定匹配字符范围的方法。

  • [:alnum:]匹配字母和数字.等同于A-Za-z0-9.

  • [:alpha:]匹配字母. 等同于A-Za-z.

  • [:blank:]匹配一个空格或是一个制表符(tab).

  • [:cntrl:]匹配控制字符.

  • [:digit:]匹配(十进制)数字. 等同于0-9.

  • [:graph:](可打印的图形字符). 匹配 ASCII 码值的33 - 126之间的字符. 这和下面提到的 [:print:]一样,但是不包括空格字符.

  • [:lower:]匹配小写字母. 等同于a-z.

  • [:print:](可打印字符). 匹配 ASCII码值 32 - 126之间的字符. 这和上面提到的一样[:graph:],但是增多一个空格字符。

  • [:space:]匹配空白字符 (空格符和水平制表符).

  • [:upper:]匹配大写字母. 等同于A-Z.

  • [:xdigit:]匹配十六进制数字. 等同于0-9A-Fa-f.

 POSIX字符类一般都要求用引号或是双方括号double brackets([[ ]])引起来.

 
bash$ 


grep [[:digit:]] test.file

 
abc=723
 	      

这些字符类在一个受限的范围内甚至可能用在能用在通配(globbing)中.

 
bash$ 


ls -l ?[[:digit:]][[:digit:]]?

 
-rw-rw-r--    1 bozo  bozo         0 Aug 21 14:47 a33b
 	      

为了理解POSIX字符类在脚本中的使用,请参考例子 12-18例子 12-19.

Sed, awk, 和Perl在脚本中被用作过滤器, "过滤"或转换文件/IO流的时候以正则表达式作为参数。参考例子 A-12例子 A-17来理解这种用法.

在正则表达式这个复杂主题的标准参考是Friedl的Mastering Regular Expressions.由Dougherty和Robbins写的 Sed & Awk也给出了一个清晰的正则表达式论述. 查看参考书目找到这个主题更多的信息.

[1]

因为Since sed, awk, 和and grep通常处理单行,而不能匹配一个新行符. 在要处理多行的一个输入时,可以使用点操作符,它可以匹配新行符。

   1 #!/bin/bash
   2
   3 sed -e 'N;s/.*/[&]/' << EOF   # Here Document
   4 line1
   5 line2
   6 EOF
   7 # 输出:
   8 # [line1
   9 # line2]
  10
  11
  12
  13 echo
  14
  15 awk '{ $0=$1 "\n" $2; if (/line.1/) {print}}' << EOF
  16 line 1
  17 line 2
  18 EOF
  19 # 输出:
  20 # line
  21 # 1
  22
  23
  24 # 多谢, S.C.
  25
  26 exit 0