BBS水木清华站∶精华区

 
组成 Regular Expression 的元素 
 
Regular Expression 是由普通字元、及一组具有特殊意义 的字元所构成. 本节主要介 
绍各种特殊字元所代表的意义及 其用法. 读者学习时应留心 : 有时, 同一特殊字元, 
会因出 现在字串中不同的位置或连接其它特殊字元, 而有不同的意义. 本文中为有别 
於一般的字串, 所有 Regular Expression 都以粗体字体表示, 且加注``Regexp''於其 
前方. 
 
组成 Regular Expression 的元素及所代表的意义如下 : 
 
   * [普通字元] 除了``.''、``[''、``]''、``*''、``+''、``?''、 ``|''、``^'' 
     、``$''、``{''、``}''、``\''、``<''、``>''、``(''、``)'' 外之所有字元. 
 
     由普通字元所组成的 Regular Expression 其意义与原字串字面意义相同. 
 
     例如: 
 
        o 普通字元``A''也可当成一个 Regular Expression. Regexp ``A'' 与一般 
          字元``A''代表相同的意义. 
        o Regexp ``the'' 与一般字串``the''代表相同的意义. 
 
   * [.] Metacharacter 用以代表任意一个字元. 须留心 UNIX Shell 中使用``?'' 
     表示任意一个字元, 使用``*''代表任意长度的字串(这是另一种称为 ``Pattern 
     Matching Notation'' 的字串表示法). Regular Expression 中则使用``.'' 来 
     代表``一个''任意字元(注 意: 并非任意长度的字串). 而 Regular Expression 
     中``*''另有 其它涵意, 并不代表任意长度的字串. 
 
     例如: 
 
        o Regexp ``.'' 可用以代表任意一个字元. 如 ``A''、``1''、``+''、... 
        o Regexp ``...'' 则代表一个由任意3个字元所的字串. 譬如 ``123''、 
          ``abc''、``# 1''、... 
 
   * [^] 限制字串必须出现於行首. (用法见下例) 
 
   * [$] 限制字串必须出现於行末. 
 
        o [例如 :] Regexp `` ^The'' 用以表示所有出现於行首的字串``The''. 
          Regexp `` The$'' 用以表示所有出现於行末的字串``The''. Regexp 
          `` ^The$'' 则用以表示一个仅含字串``The''的资料列. Regexp `` ^$'' 表示 
          一个空白的资料列(行首与行尾之间未存在任一字元). 
 
   * [\] 将特殊字元还原成字面意义的字元. Regular Expression 中 特殊字元 将 
     被解释成特定的意义. 若要表示特殊字元的字面(literal meaning) 意义时, 在 
     特殊字元之前加上 ``\'' 即可. 
 
        o [例如 :] 使用 Regular Expression 来表示字串``a.out''时, 不可写成 
          Regexp ``a.out''. 因为``.''在 Regular Expression 中是特殊字元, 
          表示任一字元. 
          可合乎(match) Regexp ``a.out'' 的字串将不只 ``a.out'' 一个; 字串 
          ``a2out'',``a3out'', ``aaout''... 都合於 Regexp ``a.out''. 
          正确的表示法应为 : Regexp ``a\.out'' 
 
     `` \'' 在 Regular Expression 中的另一个意 义是当成 Escape character. 
 
        o [例如 :] ``\t'' 用以表示 tab. ``\n'' 表示换行符号. 
 
   * [...] 『字元集合』, 用以表示两中括号间 所有的字元当中的任一个. 
        o [例如 : ] Regexp ``[123]'' 可用以表示字元 ``1''、``2'' 或 ``3''. 
          Regexp ``[Tt]'' 可用以表示字元 ``T'' 或 ``t''. 所以, Regexp 
          "[Tt]he" 表示字串 "The" 或 "the". (注意 : 一个字元集合仅代表``一个 
          ''字元.) 
     使用时, 需留心字元集合 [ ] 内不可随意留空白. 
 
        o 例如 : Regexp ``[ Tt ]'' 中括号内有空白字元, 故除了可用 以表示字 
          元``T''或``t''", 也可代表一个 `` ''(空白字元). 
 
   * [-] 字元集合中可使用 `` -'' 来指定字元的区间, 其用法如下: 
 
     Regexp ``[0-9]'' 等於 Regexp ``[0123456789]'' 用以表示任意 "一个" 阿 
     拉伯数字. 同理 Regexp ``[A-Z]'' 用以表示任意 "一个" 大写英文字母. 
 
     但应留心 : 
 
        o Regexp "[0-9a-z]" 并不等於 Regexp " [0-9][a-z]"; 前者表示一个字元 
          (阿拉伯数字或小写英文字母), 後者表示二个字元. 
        o Regexp "[-9]" 或 "[9-]" 仅用以代表字元 ``9''或 ``-''. 
 
   * [[^{...}]] 使用 [^{...}] 产生字元集合的补集(complement set). 其用法 
     如下 : 
 
        o Regexp ``[^M]'' 用以表示除字元``M''外的``一个''任意字元 
        o 字元集合 ``[Tt]''表示字元 ``T'' 或 ``t''. 若要指定 ``T'' 或 ``t'' 
          之外的任一个字元, 可用 Regexp ``[^Tt]'' 表示. 
        o Regexp ``[^a-zA-Z]''表示英文字母之外的任一个字元. 
     需留心 ``^''之位置; ``^'' 必须紧接於 ``['' 之後, 才代表字元集合的补 
     集. 
 
        o [例如 :] Regexp ``[0-9^]'' 表示一个阿拉伯数字或字元 ``^'', 并非 
          代表阿伯数字外的任意字元. 
 
   * [*] 用以形容其前的字元或字元集合可重复任意次数的特殊字元. 
     `` *'' 形容它前方之字元(或字元集合)可出现 1 次或多次, 或不出现. 例如 : 
 
        o Regexp ``ab*'' 中, ``*'' 形容它前方的字元 ``b'' 可出现 1 次或多 
          次, 或不出现. 所以, Regexp ``ab*'' 可表示字串 ``a''、``ab''、 
          ``abb''、 ``abbb''、... 
        o Regexp ``T[0-9]*\.c'' 中, 使用 ``*'' 形容其前的字元集合 `` 
          [0-9]''(一个阿拉伯数字)出现的次数 : 可为 0 次或多次. 
 
          故 Regexp ``T[0-9]*\.c''可用以表示 ``T.c''、``T0.c''、 ``T1.c''、 
          ``T2.c''、...、``T9.c''、``T00.c''、``T01.c''、``T02.c''、...、 
          ``T09.c''、``T10.c''、...``T99.c''、``T000.c''、... 
 
   * [\<] `` \< Regexp'' 表示一个出现於"字首"且又合於(match)该 Regexp 的字 
     串 (用法见下例). 
 
   * [\>] ``Regexp \>'' 表示一个出现於"字末"且又合於(match)该 Regexp 的字 
     串. 
     这里所谓的``字(word)''系指被 tab、逗点、句点或空白字元(space) 所分隔开 
     的字串. 
        o [例如 :] 
 
          资料 ``One is red, and the other is white.'' 中 字串 ``One'', 
          ``is'', ``red'', ``and'', ``the'', ``other'', ``is'', ``white'' 便 
          是所谓的 "字(word)". 而该资料列中, 
          合於 Regexp ``[Tt]he''的字串如下(粗体字标示) 
          ``One is red, and the other is white.'' 
          合於 Regexp ``\<[Tt]he\>''却仅有(粗体字标示) 
          ``One is red, and the other is white.'' 
          因同时使用`` \<''及`` \>'' 限制合於 Regexp ``[Tt]he''的字串, 必须 
          紧接於字首及字尾之间; 故 ``other''中的子字串 ``the''并不合於这个 
          Regular Expression. 
        o [注 :] \<, \> 这二个特殊字元, 并不是很通用. 请参考 Appendix A 中的 
          附表. 
        o \( ... )\ 於 Regular Expression 中使用 `` \(''``{ \)}''来括住一部 
          分的 Regular Expression; 其後可用 `` \1'''来表示第一次被`` \('' `` 
          \)'' 括住的部份. 若 Regular Expression 中使用了数次`` \('' `` \)'' 
          来括住不同的部分, 则依次使用 ``\1'', `` \2'', `` \3'' ,...(最多可 
          用到 `` \9'')来 表示之前括住的 Regular Expression. 其用法如下 : 
 
        o [用法一.] 
             + 例如: 欲表示像``aa'',``bb'',``cc'',...``zz'' 等字串. 
               使用 Regexp ``[a-z]''则表示任一个小写的英文字母. 
               使用 Regexp ``[a-z][a-z]''则表示二个任意的小写英文字母. 它除 
               表示 ``aa'',``bb'',``cc'',...``zz''等字串外, 也可表示``ab'', 
               ``ac'',``ad'',...等字串(这不是题意所要求的字串). 
               这时可以`` \('' `` \)'' 来括住第一个 `` [a-z]'' (Regular 
               Expression 解译的程式, 会暂时记录实际找寻 到的英文字母). 之 
               後, 便可以 Regexp ``\1'' 来指定适才被记 录下的英文字母即为所 
               要找寻字串的第二个字元. 故正确的表示法如下 : 
 
               Regexp ``\([a-z]\)\1'' 
             + 例如 : 欲表示像 ``789w987'', ``abcwcba'', ``theweht'',....等 
               具对称性 的字串.(该字串的特徵是 ``w''之前後三个字元相互对称) 
               该类字串的表示法如 下 : 
 
               Regexp ``\(.\)\(.\)\(.\)w\3\2\1" Regexp中``.''表示任意一个 
               字元. 因字元``w''之前出现的三个字元并无 任何限制, 故可用 `` 
               ...''表之. 但每个`` .''分别用 `` \('',`` \)'' 括住, 之後便可 
               使用 `` \1'', `` \2'', `` \3'' 分别代表将来实际匹配到的前三个 
               字元. 
 
        o 用法二. 进行字串找寻并置换(Replace)时, 若将被置入的新字串不是一个 
          固定的字串, 与被找到的原字串有关时(见下例说明). 此时, 可先以 \( \) 
          来括住一部分的Regular Expression; 再於将被新置入的字串中使用`` 
          \1'', `` \2'',... 来表示当时被找到的字串(或其子字串). 
             + 例 : 欲找出档案中具有 ``prog12.c'', ``prog9.c'', 
               ``prog832.c'',... 等式样的字串, 并将其置换成(以上列三个字串为 
               例) ``[note 12]'', ``[note 9]'', ``[note 832]''. 在这例子 
               中, 因事先不知道所找寻到的字串(prog数字.c)中的 数字 为何, 故 
               无法事先决定应换成什麽新字串. 合於本例所要找寻的字串其 
               Regular Expression 为 : 
               Regexp ``prog[0-9][0-9]*\.c'' 上式中 ``[0-9][0-9]*'' 表一位 
               或一位以上的阿拉伯数字, 因 执行前并不知道该部分实际会匹配什麽 
               数值, 故找到的字串将来应置换 成什麽, 事前无法指定. 这情况, 也 
               可用`` \('',`` \)'' 来括住 ``[0-9][0-9]* '', 在置换的新字串 
               中再以 \1 表示找寻时实际匹配到的数字. 
 
          读者可编辑一资料档, 再以sed执行下列命令, 观察其执行结果. 
 
     $sed -e 's/ prog\([0-9][0-9]*\)\.c/[ note \1]/g' 资料档名 
 
        o \{ 数字, 数字\} 一种於 Regular Expression 中形容其前的字元或字元 
          集合出现次数的表示法. 其型态与用法如下 : 
 
        o \{下限数字, 上限数字\} 
          例如 : Regexp "[0-9]\{2,4\}"用以表示2到4位的阿拉伯数字. 
        o { 数字} 
          例如 : Regexp ``ax\{99\}'' 用以表示一个 ``a'' 之後接上99个 ``x'' 
          所组成的字串. 
        o \{下限数字, \} 例如 : Regexp ``ax\{2,\}'' 用以表示一个 ``a'' 之後 
          接上2个或更多的 ``x''所组成的字串. 
 
   * [+] 形容其前的字元或字元集合出现一次或一次以上(注三). 
     例如 : Regexp ``[0-9]+'' 用以表示一位或一位以上的数字. 
 
   * [?] 形容其前的字元或字元集合可出现一次或不出现(注三). 
        o [例如 :] Regexp ``[+-]?[0-9]+'' 表示数字(一位以上)之前可出现一个正 
          负号 或不出现正负号. 
 
   * [(...)] 用以括住一群字元,且将之视成一个group(见下面说明)(注三) 
        o 例如 : 
          Regexp ``12+'' 表示字串 "12","122","1222","12222",... 
          Regexp ``(12)+'' 表示字串 "12","1212","1212","1212".... 
     上式中字串 ``12''以( )括住,整个视为一个group, 故被重覆符号``+'' 所形容 
     的是``12''而非 ``2'', 重复出现的也是 ``12''. 
 
   * [|] 表示逻辑上的 "or" (注三) 
        o 例如 : Regexp ``Oranges?|apples?|water'' 可用以表示字串 
          ``Orange'', ``Oranges'' 
          或 ``apple'', ``apples'' 
          或 ``water'' 
        o 注三 : 上列 + , ?, (...), | 等用法, 为 Extended Regular Expression 
          中新增列的用法. awk 及 egrep 中所使用的 Regular Expression 即为 
          Extended Regular Expression. 但 vi, sed, grep,...等软体中并无这些 
          用法. 
 
   * [&] ``&''并非 Regular Expression 中的特殊字元. 但以 Regular Expression 进 
     行字串找寻置换(Replace)时, 常会用到 ``\&''. \ 在许多 Unix tool 中, 当 
     ``\&''出现在『将被置入的新字串』时, 它用以表示 ``实际被找到合於所指定的 
     Regular Expression 的字串'' (见下例说明) 
        o 例如 : 找出档案中所有合乎 Regexp ``a[0-9]*\.c'' 的字串, 并在其前後 
          加上小 括号.依题意要求, 档案中所有如 ``a12.c'', ``a932.c'', 
          ``a45.c'' ,...等字串都应置换为 ``(a12.c)'', ``(a932.c)'', 
          ``(a45.c)'',.. . . 遇到这情况,可令『将被置入的新字串』为 `` (&)'' 
          此时, ``&''便是用来表示实际上被找到合於 Regexp ``a[0-9]*\.c'' 的字 
          串. 
     下列是使用 UNIX 上不同的工具, 来处理本例要求的字串置换. 
 
        o vi 以 vi 编辑该档案,并在 vi 命令输入模式下输入 
          : s/a[0-9]*\.c/(&)/g 
        o sed 执行如下命令 ( $ 表 Shell 命令列的提示符号 ) 
          $ sed -e 's/a[0-9]*\.c/ (&)/g' 资料档名称 
        o awk 执行如下命令 ( $ 表 Shell 命令列的提示符号 ) 
          $ awk '{ gsub(/a[0-9]*\.c/, "(&)"); print }' 资料档名称 
 
---------------------------------------------------------------------------- 
 
Note 2: 
     上列字元在 Regular Expression 中代表特殊意义, 称之为 特殊字元. 但 Unix 
     中不同的指令对 Regular Expression 的解释能力不尽相同, 故对特殊字元也有 
     不同的认定. 请参考尾页附表. 
 

BBS水木清华站∶精华区