正则表达式(,常简写为、或),又称規律表達式、正規-{zh-cn:表示式; zh-tw:表達式; zh-hk:表示式;}-、正規表示法、規則運算式、常規表示法,是计算机科学概念,用簡單字串来描述、匹配文中全部符合指定格式的字串,現在很多文本编辑器都支援用正則表达式搜尋、取代符合指定格式的字串。
许多程序设计语言都支援用正則表达式操作字串,如Perl就内建功能强大的正則表达式引擎。正則表达式这概念最初由Unix的工具软件(例如sed和grep)普及开。
譯名問題
描述字串規律的表達式原應順理成章稱為規律表達式(pattern expression/rule expression),但卻叫成有欠準確的regular expression,導致現在有多種中譯名,如將regular譯成規律、規則、-{zh-cn:正规; zh-tw:正則; zh-hk:正規;}-、正则或常規,將expression譯成表達式、-{zh-cn:表示式; zh-tw:表達式; zh-hk:表示式;}-、表示法或運算式等。
历史
最初的正则表达式出现于理论计算机科学的自动控制理论和形式化语言理论中。在这些领域中有对计算(自动控制)的模型和对形式化语言描述与分类的研究。
1940年,沃伦·麦卡洛克与沃尔特·皮茨将神经系统中的神经元描述成小而简单的自动控制元。
1950年代,数学家斯蒂芬·科尔·克莱尼利用称之为「正则集合」的数学符号来描述此模型。肯·汤普逊将此符号系统引入编辑器,随后是Unix上的编辑器ed,并最终引入grep。自此以后,正則表达式被广泛地应用于各种或类Unix系统的工具中。正则表达式的规范,分为基本型正则表达式(,)和扩展型正则表达式(,)两大流派。在兼容的系统上,和之类的工具都遵循规范,一些数据库系统中的正则表达式也符合规范。、、都属于,是历史最早的正则表达式,因此元字符必须转譯之后才具有特殊含义。、则属于,元字符不用转譯。
的正则表达式源自于于1986年1月19日发布的,它已经演化成了(兼容正则表达式,),一个由开发的,为很多现代工具所使用的库。
各編程语言之间關於正則表达式的整合,目前开發進展得很差。的子项目的设计中已考虑到了这点。
理论
正则表达式可以用形式化语言理论的方式来表达。正则表达式由常量和算子组成,它们分别表示字符串的集合和在这些集合上的运算。给定有限字母表Σ定义了下列常量:
- 空集\varnothing表示集合为空。
- 空串\varepsilon表示仅包含一个“不含任何字符、长度为0的字符串”的集合。
- a\in\Sigma表示仅包含一个元素a的集合\{a\}。
定义了下列运算:
- 串接 RS表示集合\{\alpha \beta \mid \alpha \in R, \beta \in S\},这里的\alpha \beta表示将\alpha和\beta两个字符串按顺序连接。例如:\{ab, c\}\{d, ef\} = \{abd, abef, cd, cef\}。
- 选择 R | S表示R和S的并集。例如:\{ab, c\} | \{ab, d, ef\} = \{ab, c, d, ef\}。
- 克莱尼(Kleene)星号 R^表示包含\varepsilon且在字符串串接运算下闭合的R的最小超集。这是可以通过R中零或有限个字符串的串接得到所有字符串的集合。例如:\{ab, c\}^ = \{\varepsilon, ab, c, abab, abc, cab, cc, ababab, \cdots \}。
上述常量和算子形成了克莱尼代数。
很多课本使用对选择使用符号\cup、+或\vee替代竖线。
为了避免括号,假定星号有最高优先级,接着是串接,接着是并集。如果没有歧义则可以省略括号。例如:(ab)c可以写为abc,而a|(b(c))可以写为a|bc。
例子:
- a|b*表示\{\varepsilon, a, b, bb, bbb, \cdots \}。
- (a|b)表示包括空串和任意数目个a或b*字符组成的所有字符串的集合:\{\varepsilon, a, b, aa, ab, ba, bb, aaa \cdots \}。
- ab(c|ε)表示开始于一个a接着零或多个b和最后一个可选的c*组成的字符串的集合:\{a, ac, ab, abc, abb, abbc \cdots \}。
为了使表达式更简洁,正则表达式也定义了?和+;aa等于a+,表示a出现至少一次;而(a|ε)等于a?,表示a出现1次或不出现。有的定义中增加了补算子\sim;\sim R表示在\Sigma^上但不在R中的所有字符串的集合。补算子在理论上并非必要,因为它可以使用其他算子来表达,但它可以使一些表达式变得更加简洁。
这种意义上的正则表达式可以表达正则语言,是可被有限状态自动机精确接受的语言类。但是在简洁性上有重要区别。某类正则语言只能用大小指数增长的自动机来描述,而要求的正则表达式的长度只线性的增长。
正则表达式对应于乔姆斯基层级的类型-3文法。但通常编程语言或其相关库(例如PCRE)中实现的正则表达式的表达能力是乔姆斯基层级中类型-3文法的超集。在另一方面,在正则表达式和不导致这种大小上的爆炸的非确定有限状态自动机()之间有简单的映射;为此经常被用作正则表达式的替表示式。
这种形式化中存在着冗余。典型的体现是,同样的语言可以用不同的正则表达式表达。对于两个给定的正则表达式,给出一个算法来判定它们所描述的语言是否相等,即简约每个表达式到极小确定有限自动机,确定它们是否同构(等价)。这种冗余最多可以减少到什么程度?存在具有完全表达力的正则表达式的最小子集吗?这是一个极为困难的问题。我们需要Kleene星号和并集来解决这些问题,但是我们可以限制它们的使用。由于正则表达式的简单性,不存在其他办法可以将其在语法上重写成某种规范形式。过去公理化的缺乏导致了。近期,用克莱尼代数公理化了正则表达式。
很多现实世界的“正则表达式”引擎实现了不能用正则表达式代数表达的特征。
基本语法
一個正则表达式通常被稱為一個模式(),為用来描述或者匹配一系列符合某个句法规则的字符串。例如:Handel、Händel和Haendel這三个字符串,都可以由H(a|ä|ae)ndel这个模式来描述。大部分正则表达式的形式都有如下的结构:
选择
- 竖线|代表选择(即或集),具有最低优先级。例如gray|grey可以匹配或。
数量限定
某个字符后的数量限定符用来限定前面这个字符允许出现的个数。最常见的数量限定符包括+、?和*(不加数量限定则代表出现一次且仅出现一次):
- 加号+代表前面的字符必须至少出现一次。(1次或多次)。例如,goo+gle可以匹配google、gooogle、goooogle等;
- 问号?代表前面的字符最多只可以出现一次。(0次或1次)。例如,colou?r可以匹配color或者colour;
- 星号代表前面的字符可以不出现,也可以出现一次或者多次。(0次、1次或多次)。例如,042可以匹配42、042、0042、00042等。
匹配
- 圆括号()可以用来定义操作符的范围和优先度。例如,gr(a|e)y等价于gray|grey,(grand)?father匹配father和grandfather。
上述这些构造子都可以自由组合,因此H(ae?|ä)ndel和H(a|ae|ä)ndel是相同的,表示{"Handel", "Haendel", "Händel"}。
精确的语法可能因不同的工具或程序而异。
PCRE表达式全集
正则表达式有多種不同的风格。下表是在中元字符及其在正则表达式上下文中的行为的一个完整列表,适用于或者编程语言(或者的正则表达式文法是的子集):
Unicode处理
在.NET、、、的正则表达式中,可以用\uXXXX表示一个字符,其中XXXX为四位16进制数字。
字符的三种性质:
- Unicode Property:字符属于标点、空格、字母等等。每个字符只能属于唯一。.NET、、和等语言支持。具体分类为:
** 字符\p{L}
*** \p{Ll}或\p{Lowercase_Letter}:小写字符(必须有大写的形式)。
*** \p{Lu}或\p{Uppercase_Letter}:大写字符(必须有小写的形式)。
*** \p{Lt}或\p{Titlecase_Letter}:全词首字母大写的字符。
*** \p{L&}或\p{Cased_Letter}:存在大小写形式的字符(, , 的组合)。
*** \p{Lm}或\p{Modifier_Letter}:音标修饰字符。
*** \p{Lo}或\p{Other_Letter}:不具有大小写的字符或字形。
** 附加符号\p{M}
*** \p{Mn}或\p{Non_Spacing_Mark}:与其他字符结合,不额外占用空间的字符,例如日耳曼語元音變音。
*** \p{Mc}或\p{Spacing_Combining_Mark}:与其他字符结合,额外占用空间的字符,例如馬拉雅拉姆文#元音字母及附標。
*** \p{Me}或\p{Enclosing_Mark}:包含其他字符的字符,例如圆圈、方块。
** 分隔符\p{Z}
*** \p{Zs}或\p{Space_Separator}:不可見的空格,但占據空間。
*** \p{Zl}或\p{Line_Separator}:分隔綫字符U+2028。
*** \p{Zp}或\p{Paragraph_Separator}:分段字符U+2029。
** 符号\p{S}
*** \p{Sm}或\p{Math_Symbol}:数学符号。
*** \p{Sc}或\p{Currency_Symbol}:通货符号。
*** \p{Sk}或\p{Modifier_Symbol}:组合为其他字符的符号。
*** \p{So}或\p{Other_Symbol}:其他符号。
** 数值字符\p{N}
*** \p{Nd}或\p{Decimal_Digit_Number}:所有文本中的数字0至9字符,不含形意符号。
*** \p{Nl}或\p{Letter_Number}:看起来像字母的符号,包含罗马数字。
*** \p{No}或\p{Other_Number}:上角标或下角标数字,或者其他不属于0至9的数字。不含形意符号。
** 标点符号\p{P}
*** \p{Pd}或\p{Dash_Punctuation}:任何种类的连字号或连接号。
*** \p{Ps}或\p{Open_Punctuation}:任何种类开括号。
*** \p{Pe}或\p{Close_Punctuation}:任何种类闭括号。
*** \p{Pi}或\p{Initial_Punctuation}:任何种类开引号。
*** \p{Pf}或\p{Final_Punctuation}:任何种类闭引号。
*** \p{Pc}或\p{Connector_Punctuation}:连接词的标点符号,如下划线。
*** \p{Po}或\p{Other_Punctuation}:其他标点符号。
** 其它符号\p{C}(包括不可见控制字符与未用码位)
*** \p{Cc}或\p{Control}:ASCII或Latin-1控制字符0x00-0x1F与0x7F-0x9F。
*** \p{Cf}或\p{Format}:不可见的格式化指示字符。
*** \p{Co}或\p{Private_Use}:私用码位。
*** \p{Cs}或\p{Surrogate}:UTF-16编码的代理对的一半。
*** \p{Cn}或\p{Unassigned}:未被使用的码位。
- Unicode Block:按照编码区间划分字符,每个中的字符编码属于一个编码区间。例如语言\p{ InCJK_Compatibility_Ideographs },.NET语言\p{IsCJK_Compatibility_Ideographs}。
- Unicode Script:按照字符所属的书写系统来划分字符。和(版本不低于1.9)支持。例如\p{Han}表示汉字(中文字符)。
这三种性质对应的字符组补集是将开头的\p改为\P,其它不变。
POSIX字符组
~-] || [\p{P}\p{S}]
|-
| [:space:] || 空白字符 || [ \t\r\n\v\f] || [\p{Z}\t\r\n\v\f]
|-
| [:upper:] || 大写字母字符 || [A-Z] || \p{Lu}
|-
| [:word:] || 字母字符 || [A-Za-z0-9_] || [\p{L}\p{N}\p{Pc}]
|-
| [:xdigit:] || 十六进制字符 || [A-Fa-f0-9] || [A-Fa-f0-9]
|}
優先權
範例
*以下使用PHP語言
:* 驗證字串是否只含數字與英文,字串長度並在4~16個字元之間:
:* 簡易的中華民國國民身分證字號驗證:
*以下使用Perl語言
:* 驗證字串是否只含數字與英文,字串長度並在4~16個字元之間:
print $str = "a1234" =~ m:^[a-zA-Z0-9]{4,16}$: ? "CONFIRM" : "FAILED";
:* 簡易的中華民國身份證字號驗證:
print $str = "a1234" =~ m"^\w[1289]\d{8}$" ? "CONFIRM" : "INVALID";
*以下使用python語言
:*使用正则表示式匹配ip地址:
import re
s=' 192.137.1.336 192.168.1.137.123 192.168.1.138 '
print(re.findall(r'(?
相關條目
*
- 扩展巴科斯范式
- Thompson构造法
注释
参考文献
外部链接
- [http://www.greenend.org.uk/rjk/2002/06/regexp.html 各种语言或工具软件的不同风格的正则表达式文法规定]
- [http://deerchao.cn/tutorials/regex/regex.htm 正则表达式30分钟入门教程]
- [http://regularexp.wordpress.com/ 正則表達式應用範例]
- [http://www.player.idv.tw/prog/index.php/%E6%AD%A3%E8%A6%8F%E5%8C%96%E8%A1%A8%E7%A4%BA%E6%B3%95 正規化表示法-ProgWiki]
- [https://regexper.com/ Regexper]
- [http://regexr.com/ RegExr: Learn, Build, & Test RegEx] ——公式上的悬浮气泡解释该规则匹配的字符串;匹配结果有对应的解释;右侧边栏有正则表达式的详细规范及图中的小抄
- [https://regex101.com/ regex101.com] ——查看匹配信息,并且会用不同的颜色将 Group 标记出来。
- [http://www.debuggex.com/ Debuggex: Online visual regex tester. JavaScript, Python, and PCRE.] ——另一个正则表达式的网页在线调试/验证器,用状态机图解输入的正则表达式的语义,并可检测输入的测试字符串是否匹配该正则表达式
评论 (0)