正则表达式中的“环视”及实际项目应用

什么是环视(lookaround)?

  • 环视结构不匹配任何字符,只匹配文本中的特定位置,这一点与单词分界符b、锚点^以及$相似,但是环视比它们更加通用,并且能够检测两侧文本。
  • 环视的四种类型
    1)顺序环视-肯定(从左至右查看文本):表达式为(?=……),匹配成功的条件为表达式能够匹配右侧文本,比如(?=d)
    2)顺序环视-否定(从左至右查看文本):表达式为(?!......),匹配成功的条件为表达式不能匹配右侧文本,比如(?!d)
    3)逆序环视-肯定(从右至左查看文本):表达式为(?<=……),匹配成功的条件为表达式能够匹配左侧文本,比如(?<=d)
    4)逆序环视-否定(从右至左查看文本):表达式为(?<!......),匹配成功的条件为表达式不能匹配左侧文本,比如(?<!)=)

环视在个人经历项目中的两个实际应用:

  • 团队管理中检测对于指定项目的权限:项目中我们是用类似38:1,749:0,188:1这样的字符串来存储团队普通成员对于各用户项目的权限,比如其中749代表ID为749的用户项目,冒号标记符后跟随的0数字表示具有查看权限,1数字则表示兼具查看和设置权限,多个用户项目权限标记间以逗号分隔,如果对于一个用户项目没有任何权限,则整个权限字符串中将不会出现该项目ID。基本结构定了之后,那么我们其中一个类似的查找检测权限问题是,已知用户权限字符串,检测对于指定项目比如749是否具有设置权限,在这里的问题情境其实就是检测用户权限字符串中是否包含749:1这个子字符串。可以有如下几种解决方式:
    1)可以不用正则表达式,先以逗号作为分隔符拆分权限字符串,可以得到一个数组,该数组每一个元素为类似749:1这样的单个项目权限标记子字符串,再检测这个数组中是否存在749:1这一元素项。
    2)匹配749:1出现情况的正则表达式为^749:1|,749:1,进一步可以简化为(^|,)749:1(注意:一个小陷阱,想想这里如果不使用正则表达式匹配,而只使用普通字符串749:1作为要查找匹配的目标会出现什么问题?)。
    3)利用环视的正则表达式为(?<!\d)749:1(我们知道D表示非数字,那么这里表达式如果修改为(?<=\D)749:1是否可以正常工作?)。
  • 千分位格式化数值(各分析页中各指标块数据用JavaScript进行逗号格式化):例如我们需要将数值298444215格式化为298,444,215,正常思维是从这个数的右边开始,每次数3位数字,如果左边还有数字的话,就加入一个逗号。如果我们能把这种思路直接用到正则表达式中当然很好,可惜正则表达式一般都是从左向右工作的。不过变换下思路,逗号应该加在“左边有数字,右边数字的个数正好是3的倍数的位置”,这样就可以使用环视来解决这个问题了。初步的正则表达式为:(?<=\d)(?=(\d\d\d)+$),并结合开发语言的replace替换功能进行全局匹配替换。(想想这里如果去掉$结果会如何?)遗憾的是,JavaScript不支持逆序环视,因此如果要使用JavaScript中的正则表达式进行处理,刚刚的匹配正则表达式就需要修改为:(\d)(?=(\d\d\d)+$),并需要结合对捕获型括号的反向引用$1进行全局匹配替换。

相关推荐