正则表达式

入门请参考:https://juejin.im/post/5b96a8e2e51d450e6a2de115
入门后可参考:https://juejin.im/post/5b6adc7ee51d4534b8587560
我以前没写过博文,我尝试去写一篇,发现真的还是比较困难的,不在于具体知识有多难,而是真的写不出来文字来,请多多包涵。所以我先只写一些正则表达式的例子,供大家赏玩。
所有的正则表达式都是在Sublime Text 3中执行测试通过的。Sublime Text 3有列选中和列编辑的功能,用起来非常非常爽,在Windows系统下可以使用Notepad++来代替。

例1

我从linux中的某个目录下使用ls -l命令,得到以下内容,现在我要保留最后一列,如何处理?
在这里插入图片描述

剖析:观察所有字符串,发现每一行都是由9部分组成,每部分之间由空格隔开,空格数量不一样(从选中情况来看,每个点代表一个空格,第一行和其它行略有不同),我们从最简单开始,先给第二行到最后一行的这些字符串定做一个模板

每一行由9部分组成,那就分9组(9个圆括号):()()()()()()()()()

每个部分之间把空格加上,原来每部分之间有几个空格,就加几个:() () () () () () () () ()
在正则表达式中,空格可以用\s来表示,\s表示很多空格,比如空白格,换行符,制表符等看不见的空格\s都可以表示,具体去查查基础资料。

接下来分析每部分都是由什么组成的:

第一部分(drwxr-xr-x):由若干个任意字符组成,至少有一个:.+ (解释一下:.表示任意字符,+表示至少有一个,也可以写成.,表示任意字符,有任意多个,可以是0个)
第二部分(9):由若干个字符组成,至少有一个:.+
第三部分(liyanlong):由若干个任意字符组成,有任意多个: .

第三部分(liyanlong): 你也可以说是由任意字符组成,至少有一个:.+
第三部分(liyanlong): 你可以说就是由liyanlong组成: liyanlong
从第四部分开始,我就不写了,你认为模板是什么,就是什么,只要能解释的通,都是对的,所以正则表达式比较灵活,没有标准答案,目的不是追求唯一和完美,而是条条大路通罗马,一百个人有一百个正则表达式,但是最终效果却都是相同的,这不是很好吗

所以以下都正确:

(.*)   (.*) (.*)  (.*)  (.*)  (.+) (.+) (.+) (.*)
`(.*)   (.*) (liyanlong)  (staff)  (.*)  (.+) (.+) (.+) (.*)`

\d表示一个数字, 我把所有数字替换成\d, 既然我们是写字符串模板,所以要考虑模板如何才能匹配到现有的字符

(.*)   (.*) (liyanlong)  (staff)  (\d\d\d)  (\d) (\d\d) (\d\d:\d\d) (.*)

\d{n:m}表示最少n个数字,最多m个数字, \d{m}表示只有m个数字,等价于\d{m,m}

(.*)   (.*) (liyanlong)  (staff)  (\d{3})  (\d{1,1}) (\d{2,2}) (\d{2}:\d{2}) (.*)

\d表示数字,[0-9]也表示数字,可以相互替换

(.*)   (.*) (liyanlong)  (staff)  ([0-9]{3})  ([0-9]{1,1}) (\d{2,2}) ([0-9]{2}:\d{2}) (.*)

好了,我就不继续写了,总之,你只要认为你的模板能匹配到截图中的字符串,那么你的模板就是对的,你写的正则表达式就是合格的,然后测试一下即可。

...

那就还剩下最后一步,就是替换,保留最后一列
最开始咱么说了,每个字符分9组,从第一左括号开始,分别用$1、$2、$3、$4…表示第一组,第二组,第三组,第四组… $0表示全部字符串,$9表示第9组,截图中的正则表达式表示“选中”字符串,然后用Replace框中的正则表达式去替换。
在这里插入图片描述
最后效果就是,留下第一行伫立在风中,你就动动手自己解决吧,只剩下最后一行了,还要什么自行车!!!

在这里插入图片描述

例2

对下图中的身份证号进行脱敏(身份证号都是我随机生成的数组序列而已,勿怪)
在这里插入图片描述

疑问:什么是脱敏?脱敏就是:把“51120510076901002X” 变成 “5112****002X”,当然了,脱敏的具体规则你来定,我定的就是这样的。
剖析:怎么处理呢?首先要做一个字符串模板,能够匹配所有字符串,然后跟例1中的类似,找个$n来替换一下就可以了。那我们来尝试写个
模板:

我们将字符串分为四组,即前4位,中间10位,后面再来3位,最后1位

先将身份证号分为四组:()()()()

明细:

第一组(前4位):\d\d\d\d、\d{4}、[0-9]{4}都可以
第二组(中间10位): 跟第一组类似,推荐用\d{10}
第三组(接下来的3位):同理:\d{3}
第四组(最后一位):可能是数字,也可能是X: \d|X (|表示或)

按最优方式最终组成:

  (\d{4})(\d{10})(\d{3})(\d|X)    使用  $1****$3$4  替换

同理,我们也可以将字符串分为三组:前面4位,中间10位,最后面4位

(\d{4})(\d{10})(\d{3}(\d|X)) 使用 $1****$3 来替换

非常简单有好使,不信你自己试试,骗你是小狗。最终效果就是这样的:
在这里插入图片描述
问题: 在(\d{4})(\d{10})(\d{3}(\d|X))中,如果我写成(\d{4})(\d{10})(\d{3}\d|X),也就是最后一组中,没有加小括号,那么正则表达式认为\d{3}\d是一伙的,X是一伙的,所以必须是嵌套一个小括号,明明白白告诉正则表达式解析器,\d{3}是独立存在的。
另外:如果我替换时,将$1****$3写成了$3****$1会出现啥情况?自己试试看,看看惊不惊喜,意不意外!!!

例3

给一个sample.html页面,然后找出所有的a标签中的链接值,即所有的href属性值。
在这里插入图片描述
剖析:
我是这么处理的:我首先通过java读取文件的方式,逐行读取文本,然后通过正则表达式匹配到a标签所在行,舍弃所有其它行。然后从正则表达式中提取href属性值。那么做这一切的关键点就是如何通过正则表大会匹配正确的文本行了。
那么正则表达式是个字符串模板,那我该怎么写这个模板呢,以为例,我是这么思考的:

以<a开头,然后是一个空格,然后有个href属性,属性值可以为任意字符串,属性值包含在’'中,然后以一个换行符结尾。我们写一个试试:

<a href='.+'>\n        # \n表示换行符

我试了一下,哎呦喂,完全可以啊,但是美中不足的一点是,我需要通过\n来匹配字符,但是我不需要这个\n, 用术语来说就是零宽度正预测先行断言, 匹配\n的这部分属于非捕获组。我们先写完,然后再解析。

<a href='(.+)'>(?=\n)

呵,完美啊,简直没毛病,可以了。下面可以不看了,直接去看例4吧。
**结语: **对于什么是捕获组,非捕获组, 还有零宽断言之类的,我希望这里抛出来,你如果不会,就要去自己找资料,掘金里有好多写得非常优秀的博文,你去翻一翻,基本都是免费的。如果你用心了,还学不会,可以找我来讨论。

好了,我们在看一个不是那么完美的正则表达式,画外音:我就是喜欢这种缺陷美

(<a)( )(href=.*?)(?=\n)

分析:
这是三个括号,我们能看懂吧,分别就是第一组,第二组,第三组,第四组

第一组匹配<a, 表示以字符串<a开始
第二组匹配一个空格
第三组匹配一个以href=开始的字符,后面可以跟任意多个任意字符。 等等.*表示匹配任意多个任意字符,最后的这个问号是个什么鬼? 最后的这个问号表示非贪婪匹配,也就是尽可能少的去匹配。举个例子:上面这个正则表达式可以匹配<a href=renyizifu\n, 也可以匹配<a href=renyizifu\n任意字符\n, 那默认是要匹配第二个的,也就是贪婪匹配,最大匹配,但是加上问号,就表示非贪婪匹配,也就是最小匹配。
第四组是一个正向零宽断言, 正向就是往前,就是紧接着,也就是字符串右边,零宽就是中间啥也不隔着,也就是紧接着,断言就是预测的意思。最后一组表达的意思就是:前三组匹配之后,紧接着要匹配一个叫做\n的字符串,\n就是换行符,别找了,肉眼是看不见滴。而且,这个断言的内容是非捕获的,也就是说,我要找的字符串啊,最后是以\n结尾的,但是\n又不属于我这个字符串的范围内的,你只管匹配就好,我不需要对你做任何操作,所以我的正则表达式模板要操作的字符串中没有非捕获的内容。

作者:Oscar酱
链接:https://juejin.im/post/5b99c1d6e51d450e436923aa
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值