Linux|系统管理|WEB开发

关注Linux,系统管理,WEB开发以及开源世界

Shell里的正规表达式

| Comments

还是来自ABS 最新版的摘录,这次是第十七章,关于正规表达式。以下是摘录和翻译。

一个表达式是一串字符 这些字符表达的意思超出了字面意思,我们称之为元字符(metacharacters).

正规表达式是一个字符或者元字符集,用来匹配或者模式(patterns)。 一个正规表达式包含以下一个或者多个情形:

  • 一个字符集. 这些字符保留他们的字面意义。 最简单的正规表达式类型就是这种由这些字符组成,而没有元字符
  • 锚(anchor). 指定正规表达式匹配的一行文本的位置。 比如, \, 和 $ 就都成为锚。
  • 修饰符(Modifiers). 它扩展或者缩小(修改) 正规表达式匹配的文本范围。修饰符包括星号(*),括号({,(,<)和反斜杠(\)

正规表达式主要用来文本匹配和字符串操作。一个正规表达式匹配单个字符或者字符集–字符串或者其一部分。

  • 星号 * – 匹配任意多个字符包括0个字符 “1133*” 匹配 11 + 一个或者多个3: 113, 1133, 1133333, 等等。
  • 点 . – 匹配任意一个字符,除了新行(newline)。 “13.” 匹配 13 + 任意一个字符(包括空格): 1133, 11333, 但是不包括13 。
  • 脱字符 \^ – 匹配一行的开始,但是也依赖上下文,有时表示一个字符集的反面,即不匹配这个字符集。
  • 美元符 $ – 匹配一行的结尾。 “XXX$” 匹配以 XXX 结尾的行。 “\$”匹配空白行。
  • 中括号 […] – 在正规表达式里匹配一个封闭字符集的单个字符。 “[xyz]” 匹配x, y, 或 z中的任何一个字符 “[c-n]” 匹配c 到 n范围字符集中的任何一个 “[B-Pk-y]” 匹配任何B到P和k到y的字符.

    “[a-z0-9]” 匹配任意一个小写字母或者数字。 “[\b-d]” 匹配任意字符,除了 b 到 d 的字符集之外。

    在这里实例中 \^ 除正规表达式的负面或者相反面的意思(类似shell里的 ! 符号的作用)。 将多个中括号表达式合在一起,通常用来匹配单词模式。”[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]” 匹配任意社会安全码。

  • 反斜杠 \ – 转义 特殊字符,使得该字符按照字面意思来解释(因此,它就不再是特殊字符了)。 “\$” 取回”$”符号本身的意思,而不是正规表达式里表示行尾的意思。 同样的, “\” 表示”" 符号的本意。
  • 转义 “尖括号” \<…\> – 标记单词边界。 尖括号必须转义,否则仅仅表示本意。 “\<the\>” 匹配单词 “the,” 但是不匹配单词 “them,” “there,” “other,” ,等等。

额外的一些元字符添加到基本集合里用在 egrep, awk, 和 Perl 里。

  • 问号 ? – 匹配0个或者一个正规表达式之前的字符,通常用来匹配单个字符。
  • 加号 + – 匹配正规表达式之前的一个或者多个字符,和 * 类似,但是不匹配0个字符。

    # GNU versions of sed and awk can use "+",
    # but it needs to be escaped.
    
    echo a111b | sed -ne '/a1\+b/p'
    echo a111b | grep 'a1\+b'
    echo a111b | gawk '/a1+b/'
    # All of above are equivalent.
    
    # Thanks, S.C.
    
  • 转义的 “大括号/花括号” \{ \} – 表示正规表达式匹配的数量。和尖括号一样,必须转义,否则只表示其本意。这个表达方式不是正规表达式集合的一部分。
    “[0-9]\{5\}” 准确匹配5个字符。 大括号在”经典” (非POSIX兼容)版的 awk里并不作为正规表达式生效。但是,GNU 扩展版本的 awk, gawk 提供了 –re-interval 可选参数使其有效(不需要转义)。

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

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

  • 圆括号 ( ) – 封装一组正规表达式。用expr提取子串或者接管道(“|”)操作时,这个表达式就显得有用。

  • | “或” 表示匹配可选字符集中的某一个。

    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.
    
  • 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 字符类通常需要引号或者双括号([[ ]])。

    bash$ grep [[:digit:]] test.file
    abc=723
    
    # ...
    if [[ $arow =~ [[:digit:]] ]]   #  Numerical input?
    then       #  POSIX char class
      if [[ $acol =~ [[:alpha:]] ]] # Number followed by a letter? Illegal!
    # ...
    # From ktour.sh example script.
    

    以上字符类甚至可以当做通配符,用做有限的扩展,比如。

    bash$ ls -l ?[[:digit:]][[:digit:]]?
    -rw-rw-r--    1 bozo  bozo         0 Aug 21 14:47 a33b
    

在筛选,文件转换或者I/0流操作中,Sed, awk, 和 Perl, 带一个正规表达的参数在脚本里用来过滤(filter)。

Comments