正则学习二三事

前端之家收集整理的这篇文章主要介绍了正则学习二三事前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

正则一直是我一大痛点,一直都想解决这个问题,但是奈何每次看到那么多符号就发蒙,所以就一直拖下去了。直到最近总是被别人问到如何在hql中使用rlike查询符合特定规则的字段,然后各种不会,结果被鄙视的一塌糊涂,无奈,这才静下心来慢慢研究。
以前看正则就是一堆符号,代表各个意思,如\d表示数字,\d+表示一个或者多个连续数字,单看每个规则都可以理解,除了组合,但是实际使用时真的很难组织到一起。归根结底还是因为对这些符号的理解不够深入。所以正则还是得多写,推荐一个在线练习的网站RegexGolf。好了,下面写写自己学习正则的一些总结吧,希望能够帮助到别人,也帮助自己总结总结。

正则的基础知识:

  • 字面值
    正则表达式由只代表自身的字面值和代表特定含义的元字符组成。 只代表自身的字面值指的是普通的字符,如abcde,特殊含义的元字符包括

    字符 含义
    \ 反斜线字符
    \0n 带有八进制值 0 的字符 n (0 <= n <= 7)
    \0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)
    \0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
    \xhh 带有十六进制值 0x 的字符 hh
    \uhhhh 带有十六进制值 0x 的字符 hhhh
    \t 制表符 (‘\u0009’)
    \n 新行(换行)符 (‘\u000A’)
    \r 回车符 (‘\u000D’)
    \f 换页符 (‘\u000C’)
    \a 报警 (bell) 符 (‘\u0007’)
    \e 转义符 (‘\u001B’)
    \cx 对应于 x 的控制符
  • 字符类
    字符类是字符在方括号中的集合。表示“找到集合里任意一个字符“。例如:

    字符 含义
    [abc] a、b 或 c(简单类)
    [^abc] 任何字符,除了 a、b 或 c(否定)
    [a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
    [a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)
    [a-z&&[def]] d、e 或 f(交集)
    [a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)
    [a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)

    从上表可以看出[]里面可进行并集/交集/差集操作。对于字符范围是根据ASCII值的大小来的,例如[A-z]也是可以的,甚至能够匹配[,但是完全不建议如此使用,推荐使用的字符范围:[0-9]/[a-z]/[A-Z]。
    字符类还有一些预定义的字符类:

    字符 含义
    . 任何字符(与行结束符可能匹配也可能不匹配)
    \d 数字:[0-9]
    \D 非数字: [^0-9]
    \s 空白字符:[ \t\n\x0B\f\r]
    \S 非空白字符:[^\s]
    \w 单词字符:[a-zA-Z_0-9]
    \W 非单词字符:[^\w]

    使用上面的预定义字符类能够更加方便的表示字符范围。需要牢记。
    注意: 区间是字符的区间,不是数字的区间。正则表达式[1-31]表示“找到一个1或一个2或一个3”,不是“找到一个从1到31的整数”。

  • 乘法器

    字符 含义
    X? X,一次或一次也没有
    X* X,零次或多次
    X+ X,一次或多次
    X{n} X,恰好 n 次
    X{n,} X,至少 n 次
    X{n,m} X,至少 n 次,但是不超过 m 次

    X可以使一个普通字面值,如a+:一个或多个a,也可以是一个字符类,如[abc]{2},表示a/b/c后跟a/b/c。
    值得注意的是优先选择更长的匹配,因为乘法器是贪婪的。如果你输入的文本是I had an aaaaawful day,该正则表达式就会在aaaaawful中匹配到aaaaa。不会在第三个a后就停止匹配。
    乘法器是贪婪的,但它不会忽略一个更好的匹配。如果你的输入文本为I had an aaawful daaaaay,之后这个正则表达式会在第一次的匹配中于aaawful找到aaa。只有在你说“给我找到另一个匹配”的时候,它才会继续搜索然后在daaaaay中找到aaaaa。
    惰性:
    正则表达式“.表示“找到一个双引号,接着找到尽可能多的字符,最后再找到一个双引号”。注意一下被.匹配的内部字符,很可能包含多个双引号。这通常不是非常有用。乘法器可通过追加问号(?)来实现惰性“.?”*表示“匹配一个双引号,跟着一个尽可能少的字符,再跟着一个双引号”。

  • 分支
    可以使用管道符号来实现匹配多种选择。

    字符 含义
    X|Y X或者Y
  • 组合
    可以使用圆括号来组合表达式。例:
    在一周中找到一天,使用(Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day,这里如果把小括号或者中括号,结果是完全不一样的,因为中括号是字符类,即里面的Mon并不是完全匹配Mon,而是只要匹配M/o/n其中一个即可。
    同时组合后面还可跟上乘法器,如:\w+(\s+\w+)*代表“找到一个或多个单词,它们以空格隔开”。

  • 边界
    边界分成:单词边界,行边界,文本边界

    1. 单词边界
      单词边界是一个单词字符和非单词字符之间的位置。记住,一个单词字符是\w,它是[0-9A-Za-z_],一个非单词字符是\W,也就是[^0-9A-Za-z_]。
      文本的开头和结尾总是当作单词边界。
      输入的文本it’s a cat有八个单词边界,分别为:文本开头-i,t-‘,’-s,s-空格,空格-a,a-空格,空格-c,t-文本结尾。
    2. 行边界
      每一块文本会分解成一个或多个行,用换行符分隔。
      注意文本不是以换行符结束,而是以行结束。然而,任何行,包括最后一行,可以包含零个字符。
      起始行位置是在一个换行符和下一行的第一个字符之间。与单词边界一样,在文本的开头也算作一个起始的行。结束行位置是在行的最后一个字符和换行符之间。与单词边界一样,文本结束也算作行结束。
    3. 文本边界
      很多实现提供一个标记,通过改变它来改变^和$的含义。从“行开始”和“行结束”变成“文本开始”和“文本结束”。其它的一些实现提供单独的元字符\A和\z来达到这个目的。

    一些表示边界的符号:

    字符 含义
    ^ 行的开头
    $ 行的结尾
    \b 单词边界
    \B 非单词边界
    \A 输入的开头
    \G 上一个匹配的结尾
    \Z 输入的结尾,仅用于最后的结束符(如果有的话)
    \z 输入的结尾

    其中^$是最常用的两个边界分隔符。

捕获和替换:

  1. 捕获组
    ()在正则中被用来表示组,同时也可以用来捕获匹配上的子串,可以拥有多个捕获组,它们甚至可以嵌套使用,捕获组从左到右进行编号,只要计算左圆括号。例如:
    对于表达式:(\w+) had a ((\w+) \w+),文本是I had a nice day,那么

    • 捕获组1是I。
    • 捕获组2是nice day。
    • 捕获组3是nice。
    • 捕获组0是I had a nice day(根据具体实现不同)

    如果表达式使用了两个捕获组,但是只捕获到一组,那么组2是空字符串。引用捕获组使用+组序号,如\1表示引用第一个捕获组。

  2. 后向引用
    可以在同样的表达式中引用同一个捕获组,这称为后向引用。
    例:表达式[abc]{2}表示“匹配aa或ab或ac or ba或bb或bc或ca或cb或cc”,但是表达式([abc])\1表示“匹配aa或bb或cc”。

以上就是正则的全部知识,其实了解正则的知识点很简单,但是真要应用到实际中还是需要通过大量的练习才能做到熟练使用。

实际案例
  1. 压缩CSS文件,去掉CSS文件中的换行以及空格
工具:Notepad++  查找:([{;])\s+  替换:\1

以上案例会不断更新,已记录一些自己对正则使用的经历。

参考文章

55分钟学会正则表达式(译) JDK API文档

猜你在找的正则表达式相关文章