• 正则表达式
    • Regular Expression(regex)
    • 是一种字符串匹配的模式(pattern),更像是一种逻辑公式
  • 可以用来检查一个串是否含有某种子串 配的子串替换
    • 从某个串中取出符合某个条件的子串
  • 语法
    • java中一些特殊的地方:
      • 在Java中,\表示:我要插入一个正则表达式的反斜线,所有其后的字符具有特殊的意义
      • 在其他语言中,\ 表示:我想要在正则表达式中插入一个普通的(字面上的)反斜杠,请不要给它任何特殊的意义。
      • 在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用
      • 简单的理解在 Java 的正则表达式中,两个 \ 代表其他语言中的一个 ,这也就是为什么表示一位数字的正则表达式是\\d,而表示一个普通的反斜杠是 \\\\
        • \\\\预编译会变成\\,而这个在正则表达式中就是一个\的意思
    • 由两种字符构成:
      • 元字符(特殊字符):表示正则表达式功能的最小单元,如*^$
        • $:匹配输入字符串的结尾位置

          • 如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '' 或 '。要匹配 $ 字符本身,请使用 $。
        • ():标记一个子表达式的开始和结束位置。

        • *:匹配前面的子表达式零次或多次

        • +:匹配前面的子表达式一次或多次

        • .:匹配除换行符 之外的任何单字符

        • ?:匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。

        • :将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符

          • 例如, 'n' 匹配字符 'n'。'' 匹配换行符。序列'\\' 匹配"\",而 '\('则匹配 "("
        • ^:如果不是在方括号内使用,是匹配输入字符串的开始位置;该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。

        • [:标记一个中括号表达式的开始。

        • {:标记限定符表达式的开始。

        • |:指明两项之间的一个选择。

      • 普通字符
        • []:匹配括号中的所有字符
          • 例如 [aeiou] 匹配字符串 "google runoob taobao" 中所有的 e o u a 字母。
        • [^]:匹配除了括号内字符的所有字符
          • 例如 [^aeiou] 匹配字符串 "google runoob taobao" 中除了 e o u a 字母的所有字母。
        • [-]:表示一个区间
          • 例如[A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母
          • 匹配除换行符(、之外的任何单个字符,相等于 [^\n\r]
        • []:匹配所有空白符,包括换行
        • []:匹配任何非空白符
        • :匹配字母、数字、下划线
          • 等价于 [A-Za-z0-9_]
        • 数字字符匹配。等效于 [0-9]
        • :非数字字符匹配。等效于 [^0-9]
        • 匹配一个字边界,即字与空格间的位置。
        • :非字边界匹配。
        • :匹配由x指明的控制字符
        • 匹配一个换页符。
        • :匹配一个换行符。
        • 匹配一个回车符。
        • 匹配一个制表符
        • 匹配一个垂直制表符。
      • 限定符(有6种)
        • *:匹配前面的子表达式零次或多次。等价于{0,}
        • +:匹配前面的子表达式一次或多次。等价于 {1,}
        • ?:匹配前面的子表达式零次或一次。等价于 {0,1}
        • {n}:n 是一个非负整数。匹配确定的 n 次。
        • {n, }:n 是一个非负整数。至少匹配n 次。
        • {n,m}:最少匹配 n 次且最多匹配 m 次。请注意在逗号和两个数之间不能有空格。
        • 贪婪和非贪婪:
          • 前提条件:整个表达式匹配成功
          • 贪婪:* +,它们会尽可能地多匹配字符,在它们的后面加上一个 ? 就可以实现非贪婪或最小匹配。
            • 就是在整个表达式匹配成功的前提下,尽可能多的匹配。
            • 比如:<div>.*</div>在适配</div>后仍然会向后匹配直到末尾
            • 而非贪婪模式:<div>.*?</div>在适配到</div>便停止,重新开始从第一个字符开始匹配
          • 非贪婪:可以限定匹配,通过在 *、+ 或 ? 限定符之后放置 ?将表达式转换为"非贪婪"表达式或者最小匹配。
          • 例子1:匹配两位数数字:
            • [1-9][0-9]?
            • [1-9][0-9]{0,1}
          • 例子2:匹配h1标签:<h1>RUNOOB-菜鸟教程</h1>
            • <.*>匹配整个标签
            • <.*?>匹配<h1>和<\h1>
            • <\w+?>匹配<h1>
    • 定位符
      • 定位符使您能够将正则表达式固定到行首或行尾
      • 这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。
      • 定位符用来描述字符串或单词的边界
      • ^ 和 $ 分别指字符串的开始与结束,述单词的前或后边界,表示非单词边界。
        • ^:匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 或 后的位置匹配。
        • \(:匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,\) 还会与 或 前的位置匹配。
        • 匹配一个单词边界,即字与空格间的位置
        • :非单词边界匹配
      • 注意:不能将限定符与定位符一起使用。由于在紧靠换行或者单词边界的前面或后面不能有一个以上位置,因此不允许诸如 ^* 之类的表达式。
      • 若要匹配一行文本开始处的文本,请在正则表达式的开始使用 ^ 字符。不要将 ^ 的这种用法与中括号表达式内的用法混淆。
      • 若要匹配一行文本的结束处的文本,请在正则表达式的结束处使用 $ 字符。
      • 若要在搜索章节标题时使用定位点,下面的正则表达式匹配一个章节标题,该标题只包含两个尾随数字,并且出现在行首:
        • /^Chapter [1-9][0-9]{0,1}$/
      • 符的位置是非常重要的。
        • 如果它位于要匹配的字符串的开始,它在单词的开始处查找匹配项。如://
        • 如果它位于字符串的结尾,它在单词的结尾处查找匹配项。如:/ter
      • 关于/b
        • It's a nice day today.
        • 'I' 占一个位置,'t' 占一个位置,所有的单个字符(包括不可见的空白字符)都会占一个位置,这样的位置我给它取个名字叫“显式位置”。
        • 注意:字符与字符之间还有一个位置,例如 'I' 和 't' 之间就有一个位置(没有任何东西),这样的位置我给它取个名字叫“隐式位置”。
        • “隐式位置”就是 关键!通俗的理解,是“隐式位置”。
        • “隐式位置” 匹配这样的位置:它的前一个“显式位置”字符和后一个“显式位置”字符不全是 。
        • 匹配a nice:a
    • 选择
      • 用圆括号()将所有选择项括起来
      • 相邻的选择项之间用|分隔
      • ()捕获分组,会把每个分组里的匹配的值保存起来
        • 多个匹配值可以通过数字n来查看,n是一个数字,表示第n个捕获组的内容
      • ?=、?<=、?!、?<! 的使用区别
        • exp1(?=exp2):查找 exp2 前面的 exp1。
          • 字符:123455runoob123runoob456
          • 正则表达式runoob(?=[])
          • 匹配数组前面的runoob字符串
        • (?<=exp2)exp1:查找exp2后面的exp1
          • 字符:123456google123runoob456
          • 正则表达式:(?<=[0-9]+)runoob
          • 匹配数字后面的runoob字符串
        • exp1(?!exp2):查找后面不是 exp2 的 exp1
          • 字符:123456google123runoob-456
          • 正则表达式:runoob(?[]+)
          • 匹配后面不是数字的runoob
        • (?<!exp2)exp1:查找前面不是 exp2 的 exp1
          • 字符:123456googlerunoob456
          • 正则表达式:(?<[]+)runoob
          • 匹配前面不是数字的runoob
    • 反向引用
      • 对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,就是在java中matcher的group中
      • 所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储
      • 缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。
      • 每个缓冲区都可以使用 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
      • 可以使用非捕获元字符 ?:、?= 或 ?! 来重写捕获,忽略对相关匹配的保存。
      • 反向引用的最简单的、最有用的应用之一,是提供查找文本中两个相同的相邻单词的匹配项的能力。
        • 例子: Is is the cost of of gasoline going up up?
        • 设计一种方法定位该句子,而不必查找每个单词的相邻重复出现
        • 正则表达式:"\\b(?i)(\\w+)\\b\\s+\\1"
          • \1 指定第一个子匹配项:要与第一个匹配到的相同
          • (?i):忽略大小写
      • 反向引用还可以将通用资源指示符 (URI) 分解为其组件。
        • 例子:将下面的 URI 分解为协议(ftp、http 等等)、域地址和页/路径:
        • http://www.runoob.com:80/html/html-tutorial.html
          • http
          • www.runoob.com
          • :80
          • /html/html-tutorial.html