《JavaScript语言精粹》第七章

87 阅读4分钟

正则表达式 Regular Expression

  • 可处理正则表达式的方法有
    1. regexp.exec
    2. regexp.test
    3. string.match
    4. string.replace
    5. string.search
    6. string.split

一个例子

  • 在Javascript程序中,正则表达式必须写在一行中。

    var url = "http://www.ora.com:80/goodparts?q#fragment";
    
    var parse_url=/^(?:(A-Za-z+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#*))?(?:\?([^#]*))?(?:#(.*))?$/;
    
    1. ^字符表示字符串的开始,它是一个标记,用来防止exec跳过不像URL的前缀
    2. (?:([A-Za-z]+):)?这个因子匹配一个协议名,但仅当它之后跟随一个:的时候才匹配。(?: ...)表示一个非捕获型分组,后缀?表示这个分组是可选的。
    3. (...)表示一个捕获型分组,一个捕获型分组将复制它匹配的文本并将其放入result数组。
    4. [...]表示一个字符类,[A-Za-z]包含26个大写和小写字母,连字符表示从A到Z,后缀+表示这个字符类将被匹配一到多次。
    5. (/{0,3})中,/表示一个应该被匹配的/,用\转义。{0,3}表示/将被匹配0次或者1~3次之间。
    6. (?::(\d+))?将匹配一个主机名,由一或多个数字、字母或者点或者-组成,-将被转义为-防止与表示范围的连字符混淆。
    7. 点 . 将匹配除行结束符之外所有字符。
    8. $表示字符串的结束。
  • 短小并简单的正则表达式是最好的。

    var parse_number=/^-?\d+(?:\.\d*)?(?:e[+\-]?\d)?$/i;
    
    1. ^和(美元符号)导致文本中的所有字符都要针对这个正则表达式进行匹配.如果仅包含^将匹配以一个数字开头的字符串,仅包含$将会匹配以一个数字结尾的字符串
    2. i标识规定当匹配字母时忽略大小写,匹配数字时候可以匹配e|E;
    3. -?,减号后边的?后缀表示这个减号是可选的。
    4. \d+的含义与[0-9]一样,匹配一个数字,后缀+规定它可以匹配一个或多个数字。
    5. (?:...)?表示一个可选的非捕获型分组。
    6. (?:e[+-]?\d+)?是另外一个可选的非捕获型分组,将匹配一个e或E、一个可选的正负号或者一到多个数字。

结构

  • 创建RegExp对象:

    1. 正则表达式字面量(优先)

      正则表达式字面量被包围在一对斜杠中

      var my_regexp = /"(?:\\.|[^\\\"])*"/g
      
      • 正则表达式标志, 添加在RegExp字面量末尾。
      1. g:全局的(匹配多次)
      2. i:忽略字符大小写
      3. m:多行(^和$能匹配结束符)
    2. RegExp构造器

      注:反斜杠\在正则表达式和字符串字面量不一样的含义,通常需要双写反斜杠及对引号进行转义

       var my_regexp = 
          new RegExp("\"(?:\\.|[^\\\\\\\"])*\"",'g');
      
      • RegExp对象属性:
      1. global: 如果g被使用,值为true
      2. ignoreCase: 如果i被使用,值为true
      3. lastIndex: 下次exec匹配开始的索引,初始值为0
      4. multiline: 如果标志m被使用,值为true
      5. source: 正则表达式源代码文本

元素

正则表达式选择

  • 一个正则表达式选择包含一个或者多个正则表达式序列,这些序列被|字符分隔。如果这些序列中任何一项符合匹配条件,那么这么选择就被匹配。
    "into".match(/in/int/)
    
    在into中匹配in,但是不会匹配int,因为in已经被匹配成功。

正则表达式序列

  • 一个正则表达式序列包含一个或者多个正则表达式因子,每个因子能选择是否跟随一个量词,这个量词决定这个因子允许被出现的次数。没有指定这个量词,则该因子被匹配一次。

正则表达式因子

  • 一个正则表达式因子可以是一个字符、一个圆括号包围的组、一个字符类、或者一个转义序列。(除控制字符和特殊字符,所有字符都被按字面处理)
    \ / [ ] ( ) { } ? + * | . ^ $
    
    1. 用\前缀来转义,字面化。不能使字母或者数字字面化
    2. 一个未被转义的 . 将匹配除行结束符以外的任何字符
    3. 一个未被转义的 $ 将匹配该文本的结束。当指定了 m 标志时,也能匹配行结束符。

正则表达式转义

  • 反斜杠\在正则表达式因子中稍微不同。
    1. \f 是换页符、 \n 是换行符 、 \r 是回车符 、 \t 是制表符 、 \u 允许指定Unicode字符表示十六进制常量,但\b不是退格符。
    2. \d 等同于[0-9]。它匹配一个数字。\D表示与其相反的[^0-9]
    3. \s 等同于[\f\n\r\t\u000B\u0020\u00A0\u2028\u2029],Unicode空白符的一个不完全子集,与\S相反。
    4. \w 等同于[0-9A-Z_a-z],\W与其相反。如果要匹配一个字母类,就必须指定自己的类
    5. \b 为一个字边界标志,方便对文本的字边界进行匹配。使用 \w 寻找边界,对多语言应用无用。
    6. \1 是指向分组1所捕获到的文本的一个引用。能够再次被匹配。\2指向分组二,以此类推。

正则表达式分组

  • 捕获型:

    • 一个捕获型分组是一个被包围在圆括号中的正则表达式选择。
  • 非捕获型:

    • 非捕获型分组有一个 (?: 前缀,仅做简单匹配,不会捕获所匹配文本。
  • 向前正向匹配:

    • 向前正向匹配有一个 (?= 前缀,匹配后文本将会回到它开始的地方,实际上并不匹配任何东西。
  • 向前负向匹配:

    • 向前负向匹配有一个 (?! 前缀,只有匹配失败时候才进行匹配。

正则表达式类

  • 正则表达式类是一种指定一组字符的便利方式
    • 如果想匹配一个元音字母,可以写(?:a|e|i|o|u),但可以方便地写成一个类[aeiou]。
    • 另外俩个方便性:
      1. 指定字符范围。
      ! " # % & () * + ' - , / : ; < = > ? @ [ \ ] ^ _ { | } ~
      
      // 可以写成
      ?:!|"|.....
      //更好看的写法
      [!-\/:-@\[-`{-~]
      // 包括从 ! 到 / ,从 : 到 @ ,从 [ 到 ` ,从 { 到 ~ 的字符。
      
      1. 类的求反。 如果 [ 后的第一个字符是^,将会排除这些特殊字符(求反)。所以 [^!-/:-@[-`{-~] 将匹配任何一个非ASCII特殊字符的字符。

正则表达式类转义

  • 字符类内部转义规则与正则表达式的因子稍有不同,[\b]是退格符, - / [ \ ] ^需要被转义。

正则表达式量词

  • 正则表达式因子可以用一个正则表达式量词来决定这个因子应该被匹配的次数,包围在一堆花括号中的一个数字表示这个因子应该被匹配的次数。
    • /www/匹配的和/w{3}/一样,{3,6}将匹配3~6次,{3,}会匹配三次或者更多。
    • ?等同于{0,1}, * 等同于{0,}, + 等于{1,}
  • 如果只有一个量词,泽趋向于贪婪性匹配。匹配尽可能多的重复直到上限。若这个量词有一个额外后缀 ? ,则趋向于懒惰行匹配,匹配尽可能少的重复。一般情况最好使用贪婪性匹配。