likes
comments
collection
share

正则的断言先行后行正反双打满足我100%的匹配需求

作者站长头像
站长
· 阅读数 17

前言

正则表达式应用 ; 日常数据处理中正则表达式是必不可少的利器,尤其是作为脚本型语言存在时,正则时必备技巧!!! 你也许并不像使用正则,因为每次书写正则很麻烦。但是正则真的很灵活,今天我们来学习下正则的占位断言功能,这个功能可以使我们的正则更加的精准

场景

Simple

  • 正则表达式中通过给匹配想设置别名,这种操作之前我介绍过,后来使用感觉很爽,这里就当作简单入门级别的。
Pattern compile = Pattern.compile("(.*)\\*\\{(?<c>\\d+)\\}");
Matcher matcher = compile.matcher("zxhtom*{3}");
if (matcher.find()) {
    System.out.println(matcher.group("c"));
}
  • 我们只需要在对应的括号内新增?<name>的形式就可以了。这个时候我们只需要去获取名字叫c的匹配内容。无需关心他在正则中的位置了。

Advanced

相信大部分人都停留在入门级别。至少我之前一直通过入门级别的技巧应付日常的开发场景。但正则并不是仅仅那些功能。了解高级技巧可以让我们优雅的使用正则

Look

  • 正则表达式领域中存在 断言 这一功能,可以理解成 java 的断言,因为这里的断言并不会占位仅仅是做正则判断是否继续作用。细分的话存在正向、负向的先行、后行的断言。

正则的断言先行后行正反双打满足我100%的匹配需求

  • 画了张图,大概描述了下什么叫先行、后行。什么叫正向、负向。
  • 如上图,我们正则中的 h 匹配到红色的地方。后面的 ?=tom 表示后面必须的 tom 字符串才能匹配,而最终匹配的内容是 h.因为断言是不占位的。
  • 那么到底什么是正向负向、先行后行啊? 断言个格式为 (?[direction][updown][pattern])
  • 其中中括号内是可变变量。
  • direction 代表先行、后行
  • updown 代表正向、负向
  • pattern 代表我们的匹配表达式。可以是我们常规的正则
概念解释公式
正向匹配内容updown 为=号
负向取反,不匹配内容updown 为 ! 号
先行从左至右匹配direction 为空
后行从右至左匹配direction 为 < 号
  • 好了现在我们知道的概念了。现在我们向匹配第一个字符的 h 该如何操作呢。

先行

  • 首先,我们采用先行的策略来匹配。先行就是从左到右的顺序,那么我们就需要看 h 后面的内容。后面的是 zxh。那么我们就可以这么写 h(?=zxh) ,那么就会寻找 hzxh 中的开头的那个 h。

后行

  • 先行的实现后,那么我们来看看后行如何实现。后行就是从右往左的顺序。那么我们就需要看 h 的左边都有啥?对~啥都没有。啥都没有在正则中有个专有符号 \b 表示单词的边界。
  • 结合我们说的负向匹配,啥都没有的取反则是任意一个符号。我们可以表示 (?!\w)
  • 所以我么可以 \bh 或者 (?<!\w)h

正则的断言先行后行正反双打满足我100%的匹配需求

小结

  • 正向、负向很好理解,就是完全匹配和取反两个作用

  • 先行、后行主要就是考虑的方向。比如现在我有一个正则 (?<=zxh)123 他会怎么匹配呢?首先我们通过 < 能够知道是后行匹配。也就是匹配的是断言左边部分。也就是匹配 zxh123 中的 123。

正则的断言先行后行正反双打满足我100%的匹配需求

  • 还有断言是不占位的。这点一定要清楚。(?<=\w)zxh 只能匹配出 zxh . 但是我想匹配在单词内部的 zxh ,且向左包含 3 个字符的单词。断言仅仅是一个标记。无法参与实际匹配的。

正则的断言先行后行正反双打满足我100%的匹配需求

  • 断言也是可以多个检测的。正常我们断言是与的关系,我们可以借助正则表达式 来失效或的效果。

正则的断言先行后行正反双打满足我100%的匹配需求

具体案例

  • 不同语言下正则表达式会有些许不同。接下来我们就分别针对我常用的语言谈谈正则的使用吧。

linux

  • 在 linux 中正则匹配个人觉得是阉割版的正则表达式。在 Linux 中大概使用到正则表达式应该有 vim 、grep 、 sed 这几个地方。
  • 而 grep 实际上是进行查找的操作。所有对于正则的使用只有匹配功能。而 sed 是对字符的操作所以 sed 中正则的使用才是很完整的。剩下的就是 vim 中正则的使用。

echo "<title>hello</title>sdf<title>nihao</title>" | sed -n '/title.\?/p'

  • 上面我们简单使用 grep 的正则表达式。sed 的查询也是一样的操作。不过需要注意的是类似于正则中的关键符号如 ()+ 这些符号使用前都需要加 \ 进行转义。

echo "hello i am zxhtom" | sed 's/\(.*\)zxhtom/\1d/'

  • 在 shell 中我们也需要注意的是字符的替换。毕竟查找匹配使用大多一致。shell 中通过 =~ 进行正则匹配。
if [[ "${version}" =~ (.*)(1.2.5\.[0-9]{4}[01]{1}[0-9]{1}[0-3]{1}[0-9]{1}.*) ]]
then
  pre=${BASH_REMATCH[1]}
  version=${BASH_REMATCH[2]}
  echo ${version}
fi

  • 上面我们就是匹配的同时获取指定匹配项,然后通过 shell 语言进行拼接达到字符替换的功能。

参考链接

JavaScript正则表达式测试

放松一刻

Correction does much, but encouragement does more. — Johann Wolfgang von Goethe

正则的断言先行后行正反双打满足我100%的匹配需求