正则学习二三事

正则一直是我一大痛点,一直都想解决这个问题,但是奈何每次看到那么多符号就发蒙,所以就一直拖下去了。直到最近总是被别人问到如何在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|YX或者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文档

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值