• 为什么要使用正则表达式

  UNIX 中提供了许多 指令 和 tools,它们具有在文件中 查找(Search)字串或替换(Replace)字串 的功能。像 grep, vi , sed, awk,...

不论是查找字串或替换字串,都得先告诉这些指令所要查找(被替换)的字串为何。若未能预先明确知道所要查找(被替换)的字串为何,只知该字串存在的范围或特征时,例如:

    (一)查找 "T0.c", "T1.c", "T2.c".... "T9.c" 当中的任一字串。

    (二)查找至少存在一个 "A"的任意字串。

  这情況下,如何告知执行查找字串的指令所要查找的字串为何。

  例 (一) 中,要查找任一在 "T" 与 ".c" 之间存在一个阿拉伯数字的字串,当然您可以列举的方式,一一把所要查找的字串告诉执行命令的指令。但例 (二) 中合乎该条件的字串有无限种可能,势必无法一一列举。此时,便需要另一种字串表示的方法(协定)。

  • 什么是正则表达式

  正则表达式(以下简称 Regexp)是一种字串表达的方式。可用以指定具有某特征的所有字串。

注:为区別于一般字串,本附录中代表 Regexp 的字串之前皆加 "Regexp"。

注:awk 程序中常以 /..../ 括住 Regexp,以区別于一般字串。

  • 组成正则表达式的元素

  普通字符:除了 . * [ ] + ? ( ) \  ^ $ 外的所有字符。

  由普通字符所组成的Regexp其意义与原字串字面意义相同。

例如:Regexp "the" 与一般字串的 "the" 代表相同的意义。

.  (Meta character):用以代表任意一字符。

  须留心 UNIX Shell 中使用 "*"表示 Wild card(通配符),可用以代表任意长度的字串。而 Regexp 中使用 "." 来代表一个任意字符(注意:并非任意长度的字串)。Regexp 中 "*" 另有其它涵意,并不代表任意长度的字串。

^  表示该字串必须出现于行首。

$  表示该字串必须出现于行末。

例如:

  Regexp /^The/ 用以表示所有 "The"出现于行首 的字串 。

  Regexp /The$/ 用以表示所有 "The"出现于行末 的字串。

\  将特殊字符还原成字面意义的字符(Escape character)。

  Regexp 中特殊字符将被解释成特定的意义,若要表示特殊字符的字面(literal meaning)意义时,在特殊字符之前加上"\"即可。

例如:

  使用Regexp来表示字串 "a.out"时,不可写成 /a.out/。因为 "."是特殊字符,表示任一字符。可符合 Regexp / a.out/ 的字串将不只 "a.out" 一个;字串 "a2out"、"a3out"、"aaout" ...都符合 Regexp /a.out/ 。正确的用法为:/ a\.out/

[...]  字符集合,用以表示两中括号间所有的字符当中的任一个。

例如:

  Regexp /[Tt]/ 可用以表示字符 "T" 或 "t"。故 Regexp /[Tt]he/ 表示 字串 "The" 或 "the"。字符集合 [...] 内不可随意留空白。

例如:

  Regexp /[ Tt ]/ 其中括号内有空白字符,除表示"T"、"t" 中任一个字符,也可代表一个 " "(空白字符)。

-  字符集合中可使用 "-" 来指定字符的区间。

例如:

  Regexp /[0-9]/ 等于 /[0123456789]/ ,用以表示任意一个阿拉伯数字。

  同理 Regexp /[A-Z]/ 用以表示任意一个大写英文字母。

但应留心:

  Regexp /[0-9a-z]/ 并不等于 /[0-9][a-z]/ ;前者表示一个字符,后者表示两个字符。

  Regexp /[-9]/ 或 /[9-]/ 只代表字符 "9"或 "-"。

[^...]  使用[^..] 产生字符集合[..]的补集(complement set)。

例如:

  要指定 "T" 或 "t" 之外的任一个字符,可用 /[^Tt]/ 表示。

  同理 Regexp /[^a-zA-Z]/ 表示英文字母之外的任一个字符。

留心:

  "^" 的位置:"^"必须紧接於"["之后,才代表字符集合的补集。

例如:

  Regexp /[0-9\^]/ 只是用以表示一个阿拉伯数字或字符"^"。

*  形容字符重复次数的特殊字符。"*" 形容它前方的字符可以不出现,也可以出现 1 次或多次。

例如:

  Regexp /T[0-9]*\.c/ 中 * 形容其前 [0-9] (一个阿拉伯数字)出现的次数可为 0次或 多次,故Regexp /T[0-9]*\.c/ 可用以表示"T.c"、"T0.c"、"T1.c"、...、"T19.c"。

+  形容其前的字符出现一次或一次以上。

例如:

  Regexp /[0-9]+/ 用以表示一位或一位以上的数字。

?  形容其前的字符可出现一次或不出现。

例如:

  Regexp /[+-]?[0-9]+/ 表示数字(一位以上)之前可出现正负号或不出现正负号。

(...)  用以括住一群字符,且将之视成一个group(见下面说明)。

例如:

  Regexp /12+/   表示字串 "12", "122", "1222", "12222",...

  Regexp /(12)+/ 表示字串 "12", "1212", "121212", "12121212"....

  上式中 12 以( )括住,故 "+" 所形容的是 12,重复出现的也是 12。

|  表示逻辑上的"或"(or)

例如:

  Regexp / Oranges? | apples?  | water/ 可用以表示:字串 "Orange", "Oranges" 或 "apple", "apples"  或 "water"

  • match是什么? 

  讨论 Regexp 时,经常遇到 "某字串匹配( match )某 Regexp"的字眼。其意思为:"这个 Regexp 可被解释成该字串"。

例如:

  字串 "the" 匹配(match) Regexp /[Tt]he/。

  因为 Regexp /[Tt]he/ 可解释成字串 "the" 或 "The",故字串 "the" 或 "The"都匹配(match) Regexp /[Th]he/。

  • awk 中提供二个关系运算符(Relational Operator,见注一) ~   !~

  它们也称之为 match、not match。但函义与一般常称的 match 略有不同。

定义如下:

  A  表示一字串,B 表示一 Regular Expression

    只要 A 字串中存在有子字串可 match( 一般定义的 match) Regexp  B,则 A ~ B 就算成立,其值为 true,反之则为 false。

    ! ~ 的定义与 ~ 恰好相反。

例如:

  "another" 中含有子字串 "the" 可 match Regexp /[Tt]he/ ,所以 "another" ~ /[Tt]he/  的值为 true。

注一:有些论著不把这两个运算符( ~, !~)与 Relational Operators 归为一类。

  • 应用 Regular Expression 解题的简例

  下面列出一些应用 Regular Expression 的简例,部分范例中会更改$0 的值,若您使用的 awk不允许用户更改 $0时 请改用 gawk。

例1:

  将文件中所有的字串 "Regular Expression" 或 "Regular expression" 换成 "Regexp"

    awk '
    {
      gsub( /Regular[ \t]+[Ee]xpression/, "Regexp")
      print
    }
    ' $*

例2:

  去除文件中的空白行(或仅含空白字符或tab的行)

    awk '
      $ !~ /^[ \t]*$/ { print }
    ' $*

例3:

  在文件中具有 ddd-dddd (电话号码型态,d 表示digital)的字串前加上"TEL : "

    awk '
    {
      gsub( /[-][-][-]-[-][-][-][-]/, "TEL : &" )
      print
    }
    ' $*

例4:

  从文件的 Fullname 中分离出 路径 与 文件名

   awk '
    BEGIN{
      Fullname = "/usr/local/bin/xdvi"
      match( Fullname, /.*\//)
      path = substr(Fullname, , RLENGTH-)
      name = substr(Fullname, RLENGTH+)
      print "path :", path," name :",name
    }
    ' $*

结果打印:

      

例5:

  将某一数值改以现金表示法表示(整数部分每三位加一撇,且含二位小数)

    awk '
    BEGIN {
      Number =
      Number = sprintf("$%.2f",Number)
      while( match(Number,/[-][-][-][-]/ ) )
      sub(/[-][-][-][.,]/, ",&", Number)
      print Number
    }
    ' $*

结果输出

      

例6:

  把文件中所有具 "program数字.f"形态的字串改为"[Ref : program数字.c]"

    awk '
    {
      while( match( $, /program[-]+\.f/ ) ){
        Replace = "[Ref : " substr( $, RSTART, RLENGTH-) ".c]"
        sub( /program[-]+\.f/, Replace)
      }
      print
    }
    ' $*

【译】 AWK教程指南 附录E-正则表达式的更多相关文章

  1. 【译】 AWK教程指南 附录D-AWK的内置变量

    因内置变量的个数不多,此处按其相关性分类说明,并未按其字母顺序排列. ARGC ARGC表示命令行上除了选项 -F, -v, -f 及其所对应的参数之外的所有参数的个数.若将"awk程序&q ...

  2. 【译】 AWK教程指南 附录A-Patterns

    awk 通过判断 Pattern 的值来决定是否执行其后所对应的Actions.这里列出几种常见的Pattern: A.1 BEGIN BEGIN 为 awk 的保留字,是一种特殊的 Pattern. ...

  3. 【译】 AWK教程指南 附录C-AWK的内建函数

    C.1 字串函数 index( 原字串, 查找的子字串 ) 若原字串中含有欲寻找的子字串,则返回该子字串在原字串中第一次出现的位置,若未曾出现该子字串则返回0. 例如: $ awk 'BEGIN{ p ...

  4. 【译】 AWK教程指南 附录B-Actions

    Actions 是由下列指令(statement)所组成: 表达式 ( 函数调用,赋值...) print 表达式列表 printf( 格式化字符串, 表达式列表) if( 表达式 ) 语句 [els ...

  5. 【译】 AWK教程指南

    前面的话: 这几天写了一个程序,在同一个目录里生成了很多文件,需要统计其中部分文件的总大小,发现经常用到的ls.du等命令都无济于事,我甚至都想到了最笨的方法,写一个脚本:mkdir一个新目录,把要统 ...

  6. 【译】 AWK教程指南 1前言

    前面的话: 这几天写了一个程序,在同一个目录里生成了很多文件,需要统计其中部分文件的总大小,发现经常用到的ls.du等命令都无济于事,我甚至都想到了最笨的方法,写一个脚本:mkdir一个新目录,把要统 ...

  7. 【译】 AWK教程指南 4通过文本内容和对比选择指定的记录

    Pattern { Action }为awk中最主要的语法.若某Pattern的值为真则执行它后面的 Action. awk中常使用"关系表达式" (Relational Expr ...

  8. 【译】 AWK教程指南 2概述

    2.1 为什么用AWK 由于awk具有上述特色,在问题处理的过程中,可轻易使用awk来撰写一些小工具:这些小工具并非用来解决整个大问题,它们只扮演解决个别问题过程的某些角色,可通过Shell所提供的p ...

  9. 【译】 AWK教程指南 10编写可与用户交互的AWK程序

    执行awk程序时,awk会自动从文件中读取数据来进行处理,直到文件结束.只要将awk读取数据的来源改成键盘输入,便可设计与awk 交互的程序.本节将提供一个该类程序的范例. 范例:本节将编写一个英语生 ...

随机推荐

  1. PAT-乙级-1032. 挖掘机技术哪家强(20)

    1032. 挖掘机技术哪家强(20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 为了用事实说明挖掘机技术到底 ...

  2. python参考手册--第9章

    1.读取命令行选项 (1)sys.args python启动时,命令行选项设置在列表sys.args中. sys.args[0]:xxx.py sys.args[1:]: 其他参数 (2)optpar ...

  3. 2013 Multi-University Training Contest 5 Partition

    思路:五边形数定理!!! 五边形数定理是一个由欧拉发现的数学定理,描述欧拉函数展开式的特性.欧拉函数的展开式如下: 亦即 欧拉函数展开后,有些次方项被消去,只留下次方项为1, 2, 5, 7, 12, ...

  4. Android 图片旋转(使用Matrix.setRotate方法)

    imageView2 = (ImageView) findViewById(R.id.img2); Bitmap bitmap = BitmapFactory.decodeResource(getRe ...

  5. minicom 配置

    问题: 1:不相应按键,只有打印 Hardware Flow Control 选择NO minicom显示中文的设置:              env LANG=en_US minicom   可以 ...

  6. 使用LinkedList实现Stack与Queue

    LinkedList数据结构是一种双向的链式结构,每一个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素. 栈的定义栈(Stack)是限制仅在线性表的一端进行插入和删除运算.(1)通常 ...

  7. SGU111 Very simple problem

    多少个平方数小于等于X,二分. PS:java BigInteger. import java.util.*; import java.math.*; public class Solution { ...

  8. 深入理解jvm

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝 ...

  9. PHP+Mysql无限分类的方法汇总

    无限分类是个老话题了,来看看PHP结合Mysql如何实现.第一种方法这种方法是很常见.很传统的一种,先看表结构表:categoryid int 主键,自增name varchar 分类名称pid in ...

  10. JavaScript DOM高级程序设计 7.向应用程序加入Ajax--我要坚持到底!

    有时候,或许是因为理解能力,也或许是因为浮躁,看东西总是不入心,而且还老是想跳过本节,或者赶紧看完本节,这样的恶性循环,让我在即没有真正的学习到知识,又打击我的学习信心,还浪费了我很多事件,我想,当遇 ...