java 正则 反向引用_正则之反向引用

前言

某日在逛stackoverflow时,发现侧边栏的Hot Network Questions里有一例codegolf的问题Does it repeat?。

挑战

好奇之下点入观看,该题主的挑战如下:

当一条字符串中含有2(组/个)连续的字符时,该字符串可以称之为“连续的字符串”。

例:2034384538452可以成为“连续的字符串”,因为其含有2次连续的3845。

请找出能够判断“连续的字符串”的方法,输入可以用字符串或数组,输入不能为空,并且字符串长度必须大于等于1。

题主使用1与0来区分true和false,挑战者也可以使用其他不同的值来区分true/false。

abcab -> 0bdefdefg-> 1Hello, World! -> 1pp.pp/pp -> 1q-> 0

21020121012021020120210121020121012021012102012021020121012021020120210121020120210201210120210121020121012021020120210121020121012021012102012021020121012021012102012101202102012021012102012021020121012021020120210121020121012021012102012021020121012021020120210121020120210201210120210121020121012021020120210121020120210201210120210201202101210201210120210121020120210201210120210121020121012021020120210121020121012021012102012021020121012021020120210121020120210201210120210121020121012021020120 -> 0

解法

所有答者中,大部分常用编程语言的答者都使用正则进行判断,例如:

PHP的解法

=preg_match('#(.+)\1#',$argn);

importre

re.compile(r'(.+)\1').search

s=>/(.+)\1/.test(s)

a->a.matches(".*(.+)\\1.*")

虽然也有使用循环对比来解答的,但这不是我的关注点。

所有正则的解法中,归根结底就是6个字符(.+)\1

.+和()的意思好理解,毕竟是常用的。\1虽然能猜到用途,但是无论如何想不起来是干啥的,进入查询模式。

反向引用(backreference)

根据揭开正则表达式的神秘面纱一文,发现原来正则除了贪婪和非贪婪外还有名为“反向引用”的高级规则。

表达式在匹配时,表达式引擎会将小括号 “( )” 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。

“\1” 引用第1对括号内匹配到的字符串,”\2” 引用第2对括号内匹配到的字符串……以此类推。

如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 “(“ 在前,那这一对为先。

在正则(.+)\1中,\1等于(.+)中匹配到的值,也就是连续2次相同的值。

尝试

使用Python进行快速尝试

deffa(regex,subject):return re.findall(regex,subject);

匹配出3连的连续字符串

fa(r'(.+)\1\1','d123123123e');#['123']

fa(r'(.+)\1\1','d112233e');#[]

#或

fa(r'((.+))\1\2','d123123123e');#['123']

匹配出html标签内的文字

fa(r'.*(.*).*','asdwas

ssdsdasdd');#[('td', 'ssd')]

fa(r'.*(.*).*','asdwasfind moresda');#[('a', '/a/b','find more')]

fa(r'.*(.*).*','asdwasfind moresda');#[('a', '/a/b', 'find more')]

总结

反向匹配在业务代码中能用的地方不是很多,假如是纯粹去掉html标签的话,php有strip_tags,python也有对应的stripogram包,简略用法看这里。

多学一点,在leetcode或codewars这类的刷题网站里以最少的代码量达到要求也能有成就感。

在这里挂个我的codewars肩章,欢迎一起来玩儿。

large

Reference

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值