1. 首页
  2. 后端

Go知识点:正则表达式

  Go知识点:正则表达式

===========

正则表达式介绍

=======

正则表达式(Regular Expression,简写为regexp、regex、RE)又称规律表达式、规则表达式、模式,是由普通字符(称为字面字符)和特殊字符(称为元字符)组成的文本模式(pattern),使用简单字符串来描述、匹配一系列符合某个句法规则的字符串。正则表达式简单说就是一种描述字符串组成规律的表示方式,用来完成搜索和替换操作。

正则表达式是一个非常强大的文本处理工具,很多文本编辑器、命令行工具和高级编程语言都支持正则表达式。注意:不同正则表达式的实现在语法和功能往往有所差别。

正则表达式分类

  • POSIX流派(Portable Operating System Interface): 细分为BRE标准(Basic Regular Expression,基本型正则表达式)和ERE标准(Extended Regular Expression,扩展型正则表达式)。ERE与BRE的功能相同,只是语法不同。此外,POSIX派系代表软件有grep、sed和awk等。
  • PCRE派系:PCRE标准(Perl-compatible Regular Expression,Perl兼容正则表达式),PCRE是为了把Perl语言中正则表达式功能移植到其他语言中,现代编程语言大部分都属于PCRE派系。
  • RE2派系:RE2是一个Google开发的正则表达式引擎(C++库),可替代PCRE、Perl和Python等正则表达式引擎。

说明:PCRE与POSIX相比,PCRE使用起来更加易用简洁(不需要转义,有更简洁字符组),功能更加丰富(非捕获分组,环顾断言,非贪婪)。如果没有特殊原因,应尽可能使用PCRE派系,让正则匹配的结果更符合我们预期。

image.png

说明:grep同时支持3种模式(POSIX BRE、POSIX ERE、PCRE)

-F, --fixed-strings       PATTERNS are strings
-G, --basic-regexp        PATTERNS are basic regular expressions. This is the default.
-E, --extended-regexp     PATTERNS are extended regular expressions
-P, --perl-regexp         PATTERNS are Perl regular expressions

正则表达式语法

image.png

  • []表示字符集合(字符组),各个字符之间是逻辑或(多选一)。[]还会将特殊字符变为普通字符,转义字符(如\n)和预定义字符集(如\d)除外。
  • -在中括号内表示字符区间(前后必须有字符,码值小在前,码值大在后)。可以同时指定多个字符区间,例如[0-24-5]。注意:-不需要被转义。
  • \表示对元字符进行转义,按文本形式处理字符,忽略其特殊意义。方括号[]和花括号{}只需转义开括号,但圆括号()两个都要转义。
  • 字符集是一种简写形式,d代表数字(digit),w代表单词(word),s代表空白字符(space)。POSIX派系有单独的字符集,而且必须出现在方括号内,所以必须写成[[:digit:]]。
    image.png
  • 限定符也称为量词,表示字符或子表达式的重复次数,默认为贪婪模式(greedy,最长匹配,优先匹配,越多越好,尽可能多,多多益善)。限定符后紧跟?表示非贪婪模式,也称为懒惰模式(lazy,最短匹配,优先忽略,越少越好,尽可能少,适可而止)。
  • 定位符也称为锚点(anchor)。\b用来匹配一个单词的开头或结尾(boundary),单词边界匹配的是一个位置(一边是单词字符,另一边不是单词字符),而不是任何实际的字符。正则可以匹配文本和位置。
  • |表示选择(逻辑或),具有最低优先级。从左往右测试每个条件,如果满足某个条件,就不会管其它条件(优先左边)。注意:[]只表示单字符,|可表示子表达式。a|b|c和[abc]表示一样,ab|bc表示ab或bc。
  • ()表示使用子表达式(subexpression)进行分组(将子表达式看成一个整体),每个分组会自动分配一个组号,规则是:从左到右按左括号顺序编号,1为第一个分组的匹配结果,依次类推。反向引用用于引用子表达式(类似变量),\num或$num。(exp)编号捕获、(?exp)和(?Pexp)命名捕获。括号的另一种用途是通过(?#comment)表示注释。
  • 断言(assertion)是一个结果为真或假的逻辑判断式。正则断言只用于匹配位置,而不是文本内容本身。常见的断言有三种:单词边界、行的开始/结束、环视。
  • 环视(look-around,停在原地四处张望)就是要 求匹配部分的前面或后面要满足(或不满足)某种规则。环视本身不匹配任何字符(不消耗字符),因此也称零宽断言。肯定顺序环视(positive look-ahead)记法为(?=exp),表示匹配exp前面的位置。 肯定逆序环视(positive look-behind)记法为(?<=exp),表示匹配exp后面的位置。

记忆:=肯定、?否定、<逆序

('/(?=\d{3})/g', '12345')       肯定顺序环视:右侧必须出现3个数字的位置(0-0、1-1、2-2)
('/(?!\d{3})/g', '12345')       否定顺序环视:右侧不能出现3个数字的位置(3-3、4-4、5-5)
('/(?<=\d{3})/g', '12345')      肯定逆序环视:左侧必须出现3个数字的位置(3-3、4-4、5-5)
('/(?<!\d{3})/g', '12345')      否定逆序环视:左侧不能出现3个数字的位置(0-0、1-1、2-2)       
示例
('/foo(?=bar)/g', 'foobar foobaz')='foo'
('/(?<=foo)bar/g', 'foobar fuubar')='bar'
  • 有些正则表达式实现允许通过元字符(\l、\L、\u、\U)对字母进行大小写转换。
  • 控制选项也称为修饰符。
g 模式: global. All matches (don't return after first match)---全局模式
m 模式: multi line. Causes ^ and $ to match the begin/end of each line (not only begin/end of string)---多行模式,改变^和$的匹配行为
i 模式: insensitive. Case insensitive match (ignores case of [a-zA-Z])---不区分大小写
s 模式: single line. Dot matches newline characters---单行模式也称点号通配模式,改变.的匹配行为
U 模式: Ungreedy. The match becomes lazy by default. Now a ? following a quantifier makes it greedy---懒惰模式
x 模式: extended. Spaces and text after a # in the pattern are ignored---注释模式,让正则变得更容易阅读和维护

说明:正则表达式中分支结构/选择结构通过竖线|表示(x|y),顺序结构/连接结构没有通过元字符,而是通过前后顺序表示(xy),循环结构/重复结构通过量词表示(x{n,m})。

正则表达式测试

(1)在线测试

regex101是一个在线的正则表达式测试和学习工具,可以帮助用户测试和调试正则表达式。

image.png

说明:regex101支持设置语言为中文

image.png

(2)本地测试

pcre正则表达式库提供相应工具(pcretest)用于测试正则表达式是否正确。

image.png

输入pcretest命令,在re>后输入要测试的正则表达式(必须放在//之间,也称为界定符),在data>后输入要处理的文本,回车后显示的就是0,0,0,1,$2等各部分显示的值。在data>后输入回车进入re模式。

正则表达式原理

正则表达式使用的理论模式是有穷自动机,其具体实现称为正则引擎(Regex Engine)。使用正则表达式处理字符串,首先需要生成自动机(编译为正则对象),正则引擎根据输入字符串在进行一系列状态转移。同一个正则表达式对应有穷自动机不止一台,可以有若干台,这些有穷自动机是等价的。

有穷自动机(finite automaton)也称有穷状态自动机(finite-state machine),这种机器具备有限个状态,可以根据不同的条件在状态之间转移。有穷自动机必须满足4个条件:(1)有限多个状态(2)有一套状态转移函数(或者规则)(3)有一个开始状态(4)有一个或多个最终状态

正则引擎主要分为DFA和NFA两类,其中NFA又分为传统NFA和POSIX NFA。DFA和NFA之间存在等价关系

  • DFA(Deterministic finite automaton,确定型有穷自动机):任何时刻状态都是确定的。以文本为主导,先看文本,再看正则表达式。整个匹配过程字符串不会回溯,相同字符不会被测试两次(只看一遍)。DFA引擎更快一些,但没有反向引用、捕获分组等功能。
  • NFA(Nondeterministic finite automaton,非确定型有穷状态自动机):某个时刻状态可能是不确定的,所以必须保存所有可能的状态,在某个状态不可行时回退到之前状态,即回溯(backtracking)。以正则表达式为主导,先看正则表达式,再看文本。整个匹配过程可能会回溯,字符串中同一部分有可能被反复测试很多次。在最坏情况下,NFA执行速度可能非常慢,但NFA具有许多DFA无法提供的功能。

POSIX NFA与传统NFA类似,传统NFA“急于”报告匹配结果,找到第一个匹配就返回;POSIX NFA确保找到最左侧最长匹配。POSIX NFA的应用很少,主要是Unix/Linux中的某些工具。

回溯是指在匹配过程中,由于模式匹配失败而回退到之前的位置,重新尝试匹配的过程。回溯只属于NFA引擎,并且只有在正则中出现量词或多选分支结构时,才可能会发生回溯。回溯是正常过程,但回溯会影响正则表达式的性能,因为回溯的次数越多,所需的时间和计算资源就越多,可能会导致匹配性能下降。

image.png

正则表达式优化

  • 测试正则表达式性能:ipython测试时间消耗或regex101查看匹配次数
  • 提前编译好正则表达式缓存起来(避免反复构造自动机)
  • 尽量准确表达意图:(1)尽量不使用.*(2)字符组优于多选分支(4)锚点(5)少用贪婪模式(避免回溯),多用独占模式
  • 对于多选分支提取公共部分,并且出现概率大的放左边
  • 只在必要时使用分组,尽量使用非捕获分组(?:)。警惕嵌套的分组重复,例如(.*)*

正则表达式和通配符

  • 正则表达式用于匹配字符串,属于包含匹配,常用命令有grep,awk,sed等。
  • 通配符用于匹配文件名或目录名,属于完全匹配,常用命令有find,ls,cp等。

通配符和正则表达式看起来有点像,但不能混淆,正则表达式比通配符复杂多。通配符中可以匹配0个或多个字符,而在正则表达式中表示重复之前的一个或者多个字符,不能独立使用的。注意:+不是通配符。

image.png

参考资料

《精通正则表达式》

《正则表达式必知必会》

《正则指引》

《正则表达式入门课》

正则表达式 – 维基百科

Regex cheatsheet

正则表达式30分钟入门教程

正则表达式 – POSIX & PCRE

觅迹寻踪之正则表达式

浅谈正则表达式——从原理到实战

正则表达式入门课

Linux/Unix 工具与正则表达式的 POSIX 规范

刨根究底正则表达式之一:正则表达式概述

命令行通配符教程

原文链接: https://juejin.cn/post/7372393680596647962

文章收集整理于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除,如若转载,请注明出处:http://www.cxyroad.com/17388.html

QR code