正则表达式, regex
Contents
正则表达式, regex
|
|
元字符 描述
将下一个字符标记为一个特殊字符, 或一个原义字符, 或一个向后引用, 或一个八进制转义符。例如,“n” 匹配字符 “n”。"\n” 匹配一个换行符。
[中括号]
[]
是定义匹配的字符范围
|
|
{大括号}
{}
一般用来表示匹配的长度, 比如 \s{3}
表示匹配三个空格,\s{1,3}
表示匹配一到三个空格。
PCRE
PCRE: Perl-compatible regular expressions
^
匹配字符串的开始位置$
匹配字符串的结束位置\
将下一个字符标记为一个特殊字符(File Format Escape)、或一个原义字符(Identity Escape,有^$()*+?.[{|
共计12个)、或一个向后引用(backreferences)、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。序列“\”匹配“\”而“(”则匹配“(”。.
匹配除\r
\n
之外的任何单个字符。要匹配包括\r
\n
在内的任何字符,请使用像(.|\r|\n)
的模式。*
匹配前面的子表达式零次或多次。例如,zo能匹配“z”、“zo”以及“zoo”。等价于{0,}。+
匹配前面的子表达式一次或多次。例如,“zo+"能匹配"zo"以及"zoo”,但不能匹配"z”。+等价于{1,}。(pattern)
匹配pattern并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。可带数量后缀。?
匹配前面的子表达式零次或一次。例如,“do(es)?“可以匹配"does"或"does"中的"do”。?等价于{0,1}。{n}
n 是一个非负整数。匹配确定的 n 次。例如,“o{2}“不能匹配"Bob"中的"o”,但是能匹配"food"中的两个o。{n,}
n 是一个非负整数。至少匹配n次。例如,“o{2,}“不能匹配"Bob"中的"o”,但能匹配"foooood"中的所有o。“o{1,}“等价于"o+”。“o{0,}“则等价于"o_"。{1,3}
匹配一次到三次
linux 测试正则表达式
https://anjia0532.github.io/2017/06/29/nginx-regex-test-way/
|
|
正则表达式 “派别” 简述
相信大家对于正则表达式都不陌生,在文本处理中或多或少的都会使用到它。但是,我们在使用 linux 下的文本处理工具如 awk、sed 等时,正则表达式的语法貌似还不一样,在 awk 中能正常工作的正则,在 sed 中总是不起作用,这是为什么呢?
这个问题产生的缘由是因为正则表达式不断演变的结果,为了弄清楚这些工具使用的正则语法的不同,我们有必要去简单了解下正则的演变过程,做到知己知彼。当然这个过程本身也是很精彩的,我这里抛砖引玉,希望对大家正确使用正则表达式有所帮助。
诞生期
正则表示式这一概念最早可以追溯到 20 世纪 40 年代的两个神经物理学家 Warren McCulloch 与 Walter Pitts,他们将神经系统中的神经元描述成小而简单的自动控制元;紧接着,在 50 年代,数学家 1950 年代,数学家 Stephen Kleene 利用称之为“正则集合”的数学符号来描述此模型,并且建议使用一个简单的概念来表示,于是 regular expressions 就正式登上历史舞台了。插播一下,这个 Kleene 可不是凡人,大家都知道图灵是现代人工智能之父,那图灵的博导是Alonzo Church,提出了 lambda 表达式,而 Church 的老师,就是 Kleene 了。关于 lambda,之前也写过一篇文章,大家可以参考编程语言的基石 —— Lambda calculus。
在接下来的时间里,一直到 60 年代的这二十年里,正则表示式在理论数学领略得到了长足的发展,Robert Constable 为数学发烧友们写了一篇总结性文章The Role of Finite Automata in the Development of Modern Computing Theory,由于版权问题,我在网上没找到这篇文章,大家有兴趣的可以参考 Basics of Automata Theory。
Ken Thompson 大牛在1968年发表了 Regular Expression Search Algorithm 论文,紧接着 Thompson根据这篇论文的算法实现了 qed,qed 是 unix上编辑器ed 的前身。ed 所支持的正则表示式并不比 qed的高级,但是 ed是第一个在非技术圈广泛传播的工具,ed 有一个命令可以展示文本中符合给定正则表达式的行,这个命令是 g/Regular Expression/p,在英文中读作 “Global Regular Expression Print”,由于这个命令非常实用,所以后来有了 grep、egrep 这两个命令。
成长期
相比 egrep,grep 只支持很少的元符号,*
是支持的 (但不能用于分组中),但是 +, | 与 ? 是不支持的;而且,分组时需要加上反斜线转义,像\( ...\)
这样才行,由于 grep 的缺陷性日渐明显,AT&T的Alfred Aho 实在受不了了,于是 egrep 诞生了,这里的 e 表示 extended,加强版的意思,支持了 +、|与?这三个元符号,并且可以在分组中使用 *,分组可以直接写成 (…),同时用 \1,\2… 来引用分组。
在 grep、egrep 发展的同时,awk、lex、sed 等程序也开始发展起来,而且每个程序所支持的正则表达式都或多或少的和其他的不一样,这应该算是正则表达式发展的混乱期,因为这些程序在不断的发展过程中,有时新增加的功能因为bug原因,在后期的版本中取消了该功能,例如,如果让 grep支持元符号+的话,那么grep就不能表示字符 + 了,而且grep的老用户会对这很反感。
成熟期
这种混乱度情况一直持续到了 1986年。在1986年,POSIX (Portable Operating System Interface) 标准公诸于世,POSIX制定了不同的操作系统都需要遵守的一套规则,当然,正则表达式也包括其中。
当然,除了 POSIX 标准外,还有一个 Perl 分支,也就是我们现在熟知的 PCRE,随着 Perl 语言的发展,Perl 语言中的正则表达式功能越来越强悍,为了把 Perl 语言中正则的功能移植到其他语言中,PCRE 就诞生了。现在的编程语言中的正则表达式,大部分都属于 PCRE 这个分支。
下面分别所说这两个分支。
POSIX 标准正则
POSIX 把正则表达式分为两种 (favor): BRE (Basic Regular Expressions) 与 ERE (Extended Regular Expressions ) 。所有的 POSIX 程序可以选择支持其中的一种。具体规范如下表:
从上图可以看出,有三个空白栏,那么是不是就意味这无法使用该功能了呢?答案是否定的,因为我们现在使用的linux发行版,都是集成GNU套件的,GNU是Gnu’s Not Unix的缩写,GNU 在实现了 POXIS 标准的同时,做了一定的扩展,所以上面空白栏中的功能也能使用。下面一一讲解:
BRE 如何使用 +、?呢?需要用 \+、\?
BRE 如何使用|呢? 需要用 |
ERE 如何使用 \1、\2…\9这样的反引用?和BRE一样,就是\1、\2…\9
通过上面总结,可以发现: GNU中的ERE与BRE的功能相同,只是语法不同 (BRE需要用\进行转义,才能表示特殊含义) 。例如a{1,2},在ERE表示的是a或aa,在BRE中表示的是a{1,2}这个字符串。为了能够在Linux下熟练使用文本处理工具,我们必须知道这些命令支持那种正则表达式。现对常见的命令总结如下:
使用 BRE 语法的命令有: grep、ed、sed、vim 使用 ERE 语法的命令有: egrep、awk、emacs
当然,这也不是绝对的,比如 sed 通过-r 选项就可以使用 ERE 了,大家到时自己 man 一下就可以了。
还值得一提的是 POSIX还定义了一些 shorthand,具体如下:
|
|
在使用这些shorthand时有一个约束: 必须在[]
中使用,也就是说如果像匹配0-9
的数字,需要这么写[[:alnum:]],取反就是[^[:alnum:]]。shorhand 在BRE与EBE中的用法相同。
如果你对 sed、awk 比较熟悉,你会发现我们平常在变成语言中用的\d、\w在这些命令中不能用,原因很简单,因为POSIX规范根本没有定义这些shorthand,这些是由下面将要说的PCRE中定义的。
PCRE 标准
PCRE: Perl Compatible Regular Expressions:perl 语言兼容正则表达式
Perl 语言第一版是由 Larry Wall 发布于1987年12月,Perl 在发布之初,就因其强大的功能而一票走红,Perl 的定位目标就是“天天要使用的工具”。 Perl 比较显诸特征之一是与 sed 与 awk 兼容,这造就了 Perl 成为第一个通用性脚本语言。
随着 Perl 的不断发展,其支持的正则表达式的功能也越来越强大。其中影响较大的是于 1994年10月发布的 Perl 5,其增加了很多特性,比如 non-capturing parentheses、lazy quantifiers、look-ahead、元符号\G等等。
正好这时也是 WWW 兴起的时候,而 Perl 就是为了文本处理而发明的,所以 Perl 基本上成了 web 开发的首选语言。Perl 语言应用是如此广泛,以至于其他语言开始移植 Perl,最终 Perl compatible (兼容) 的 PCRE 诞生了,这其中包括了 Tcl, Python, Microsoft’s .NET , Ruby, PHP, C/C++, Java 等等。
前面说了 shorthand 在 POSIX 与 PCRE 是不同的,PCRE 中我们常用的有如下这些
|
|
关于 shorthand在两种标准的比较,更多可参考 Wikipedia
总结
我相信大家最初接触正则表达式 (RE) 这东西,都是在某个语言中,像 Java、Python 等,其实这些语言的正则表达式都是基于 PCRE 标准的。 而 Linux 下使用各种处理文本的命令,是继承自 POSIX标准,不过是由 GNU扩展后的而已。
大家如果对 sed、awk 命令不熟悉,可以参考耗子叔下面的两篇文章:
sed 简明教程 awk 简明教程
其它参考
GNU Regular Expression Extensions POSIX Bracket Expressions Different types of regular expressions Gnulib supports Regular_expression Linux/Unix工具与正则表达式的POSIX规范
{n,m} m 和 n 均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}“将匹配"fooooood"中的前三个o。“o{0,1}“等价于"o?"。请注意在逗号和两个数之间不能有空格。 ? 当该字符紧跟在任何一个其他限制符 (_,+,?,{n},{n,},{n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串"oooo”,“o+?“将匹配单个"o”,而"o+"将匹配所有"o”。 .点 匹配除"n"之外的任何单个字符。要匹配包括"n"在内的任何字符,请使用像”(.|n)“的模式。 (pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用”(“或”)"。 (?:pattern) 匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符”(|)“来组合一个模式的各个部分是很有用。例如"industr(?:y|ies)“就是一个比"industry|industries"更简略的表达式。
(?=pattern) 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)“能匹配"Windows2000"中的"Windows”,但不能匹配"Windows3.1"中的"Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)“能匹配"Windows3.1"中的"Windows”,但不能匹配"Windows2000"中的"Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?<=pattern) 反向肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows”,但不能匹配"3.1Windows"中的"Windows”。
(?<!pattern) 反向否定预查,与正向否定预查类似,只是方向相反。例如”(?<!95|98|NT|2000)Windows"能匹配"3.1Windows"中的"Windows”,但不能匹配"2000Windows"中的"Windows”。
x|y 匹配x或y。例如,“z|food"能匹配"z"或"food”。"(z|f)ood"则匹配"zood"或"food”。
b 匹配一个单词边界,也就是指单词和空格间的位置。例如,“erb"可以匹配"never"中的"er”,但不能匹配"verb"中的"er”。
B 匹配非单词边界。“erB"能匹配"verb"中的"er”,但不能匹配"never"中的"er”。
cx 匹配由x指明的控制字符。例如,cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的"c"字符。
d 匹配一个数字字符。等价于[0-9]。
D 匹配一个非数字字符。等价于[^0-9]。
f 匹配一个换页符。等价于x0c和cL。
n 匹配一个换行符。等价于x0a和cJ。
r 匹配一个回车符。等价于x0d和cM。
s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ fnrtv]。
S 匹配任何非空白字符。等价于[^ fnrtv]。
t 匹配一个制表符。等价于x09和cI。
v 匹配一个垂直制表符。等价于x0b和cK。
w 匹配包括下划线的任何单词字符。等价于”[A-Za-z0-9_]"。
W 匹配任何非单词字符。等价于”[^A-Za-z0-9_]"。
xn 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“x41"匹配"A”。“x041"则等价于"x04&1”。正则表达式中可以使用ASCII编码。
num 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,"(.)1"匹配两个连续的相同字符。
n 标识一个八进制转义值或一个向后引用。如果n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字 (0-7) ,则n为一个八进制转义值。
nm 标识一个八进制转义值或一个向后引用。如果nm之前至少有nm个获得子表达式,则nm为向后引用。如果nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字 (0-7) ,则nm将匹配八进制转义值nm。
nml 如果n为八进制数字 (0-3) ,且m和l均为八进制数字 (0-7) ,则匹配八进制转义值nml。
un 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,u00A9匹配版权符号 (©) 。
换行 \n
空格 \s
非 “非"是正则表达式中最难处理的逻辑关系。因为没有直接对应的结构,“非"的处理比较吃力。
最简单的"非”,意思是此处不能出现某个字符,这一点通常很直观,似乎用排除型字符组『[^…]』就可以解决。比如双引号字符串的匹配,首尾两个双引号很容易匹配,其中的内容肯定不是双引号 (暂时不考虑转义的情况) ,所以可以用『[^”]』表示即可,其长度不确定,所以用_来限定,所以整个表达式就是『"[^”]_"』,非常简单。
但是,事情果真都如此简单吗?我们仍然举cat和cut的例子,如果仍然希望匹配c开头、t结尾的单词,但不希望匹配cut,可以写成『c[^u]t』,是否就可以了?
这个表达式的意思是: 最开头的字母是c,之后是一个不为u的字符,之后是t。没错,它确实不会匹配cut,也可以匹配cat。但是,chart、conduct、court等等,它也没法匹配,因为[^u]的意思是: 匹配一个不是u的字符。
那么,把『[^u]』改成『[^u]+』好了,这样应该就可以解决问题了。但是真的如此吗?『[^u]+』的意思是,一个或若干 (最多到无穷) 个字符,但每一个字符都不能是u。所以,尽管『c[^u]+t』能匹配cat和chart,却不能匹配conduct和court。
在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。
在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。
很可能你使用过Windows/Dos下用于文件查找的通配符(wildcard),也就是_和?。如果你想查找某个目录下的所有的Word文档的话,你会搜索_.doc。在这里,*会被解释成任意的字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求——当然,代价就是更复杂——比如你可以编写一个正则表达式,用来查找所有以0开头,后面跟着2-3个数字,然后是一个连字号”-",最后是7或8位数字的字符串(像010-12345678或0376-7654321)。
合法E-mail地址
- 必须包含一个并且只有一个符号“@”
- 第一个字符不得是“@”或者“.”
- 不允许出现“@.”或者.@
- 结尾不得是字符“@”或者“.”
- 允许“@”前的字符中出现“+”
- 不允许“+”在最前面,或者“+@”
正则表达式如下:
|
|
|
|
http://deerchao.net/tutorials/regex/regex.htm
http://blog.csdn.net/newjerryj/article/details/7621014
http://www.infoq.com/cn/news/2011/04/regular-expressions-4
https://my.oschina.net/u/3080373/blog/1550653
https://liujiacai.net/blog/2014/12/07/regexp-favors/
https://www.cnblogs.com/netsa/p/6383094.html
作者:Mage 链接:https://www.jianshu.com/p/1af0493b474d 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
fnmatch syntax
github 的 branch protoction 用的是
Author -
LastMod 2022-09-15