正规表示式 (Regular Expression) 语法整理

正规表示式 (Regular Expression, 简写 regex、regexp 或 RE) 是用于字串比对的小型语言,又称正则表达式、正规表示法、规则运算式、常规表示法 (Wiki)。

很多程式语言和软件都会附加“正规表示式”这项功能。在字串的处理上,针对大量、重复、有固定逻辑的文字,正规表示式是非常强而有力的工具! 即便不是程式设计师,在可以在运用到正规表示式的场合 (例如: 文字编辑器),能帮你节省许多文字处理的时间。但是不同的软件所附加的正规表示式可能略有差异,这部份就要稍加留意。

不过在初学者的眼中,正规表示式却又像是天书一样的难以理解。以下文章针对正规表示式的相关语法做解说,你可到线上测试工具,以实际的例子去做测试。

语法整理 (Pattern)

字符符号

  • .: 任意文字、数字及符号,但不包括换行
  • \d: 任意数字 (同 [0-9])
  • \w: 任意文字、数字或底线 (同 [0-9a-zA-Z_])
  • \s: 任意空白字符,包含空白、定位、换行字符 (同 [ \t\n])
  • \D: 任意非数字
  • \W: 任意非文字、数字或底线
  • \S: 任意非空白字符 (同 [^ \t\n])
  • \n: 换行字符
  • \t: 定位字符
  • \OCT: 八进制字符,ex: \101 = "A"
  • \xHEX: 十六进制字符,ex: \x41 = "A"
  • \uUnicode: Unicode 字符,ex: \u4F60 = "你"。
    另外,Unicode 中文范围: [\u4E00-\u9FA5],中日韩文字范围: [\u4E00-\u9FFF]
  • \: 不转译控制符号

一般状态下,字符符号都不包括换行字符 (\n),因此遇到“换行”就会停止比对。在某些环境下可以启用多行模式 (Multiline),则换行字符 (\n) 会被视为一般文字。

字符列举

列举的原则:

  1. 放在中括号 [ ... ] 里的字符皆为单独比对的字符
  2. 在中括号内加 ^ 表示“反向列举”
  3. 可以用 - 来代表连续的字符范围

范例:

  • [0123456789]: 任意数字 (同 \d)
  • [0-9]: 任意数字,同 (同 \d)
  • [a-z]: 任意小写英文字母
  • [a-zA-Z]: 任意大小写的英文字母
  • [0-9a-zA-Z]: 任意数字、英文字母
  • [^x]: 反向列举,任意非 x 的字符
  • [^0-9]: 反向列举,任意非数字 (同 \D)

字串行举

  • |: 或

次数符号、限定符号

  • *: 重复 0 次以上 (同 {0,}) *贪婪原则
  • +: 重复 1 次以上 (同 {1,}) *贪婪原则
  • ?: 重复 0 或 1 次 (同 {0,1}) *贪婪原则
  • {n}: 重复 n 次
  • {n,}: 重复 n 次以上 *贪婪原则
  • {0,n}: 重复 0 ~ n 次 *贪婪原则
  • {n,m}: 重复 n ~ m 次 *贪婪原则

说明:

  1. 所有的“次数符号”都会极大化 (Infinite) 要比对的范围,称为“贪婪原则”。
    ex: .*\d+ 因为贪婪原则,前面的 .* 就已经涵盖后面的 \d+ 所要比对的数字了,因此 \d+ 在这里是多余的!
  2. 如果要取消“贪婪原则”,只要在次数符号的后面加上 ? 即可让它节制一点、不要那么的贪婪,让放在后面的比对规则也可以有作用。因此,上面的范例就变成: .*?\d+
  3. 在实务上,我们不太会将 *? 这两个次数符号放在正规表示式的最后,因为它们两者都允许“重复 0 次”,因为比对之后可能会多出“空白”的结果。

边界符号

  • ^: 要在行的开头 (Start of line)
  • $: 要在行的结尾 (End of line)
  • \b: 必须是单词 (文字、数字、底线) 的开头或结尾
  • \B: 不能是单词 (文字、数字、底线) 的开头或结尾

进阶

群组

  1. 可以使用小括号 ( ... ) 将既有的规则组合成一个“群组”
  2. 建立规则群组之后,可再以此群组为基础,套用其它的规则
  3. 可以用 \1 ... \9 来代表前面符合的群组
  4. 当要储存或取代比对的内容时,可以用 $1 .. $9 (或 \1 ... \9) 来代表各群组

判断式

右合、正看 (Lookahead):

  1. Pattern1(?:Pattern2): 符合 Pattern1 并且右方符合 Pattern2 才算符合全部的 Pattern
    ex: Windows(?:95|98|2000) 可符合 Windows95,但不符合 WindowsNT
  2. Pattern1(?=Pattern2): 符合 Pattern1 并且右方符合 Pattern2 才算符合 Pattern1
    白话文: 我要找 Pattern1,其右方必须为 Pattern2
    ex: Windows(?=95|98|2000) 可符合 Windows95 的 Windows,但不符合 WindowsNT 的 Windows
  3. Pattern1(?!Pattern2): 符合 Pattern1 但右方不符合 Pattern2 才算符合 Pattern1
    白话文: 我要找 Pattern1,但右方不能为 Pattern2
    ex: Windows(?!95|98|2000) 可符合 Widnows 或 WindowsNT 的 Windows,但不符合 Windows95 的 Windows

左合、回头看 (Lookbehind):

  1. (?<=Pattern1)Pattern2: 符合 Pattern2 并且左方符合 Pattern1 才算符合 Pattern2
    白话文: 我要找 Pattern2,其左方必须为 Pattern1
    ex: (?<=Chapter|Section)[\d]+ 可符合 Chapter15 的 15,但不符合 Topic15 的 15
  2. (?<!Pattern1)Pattern2: 符合 Pattern2 但左方不符合 Pattern1 才算符合 Pattern2
    白话文: 我要找 Pattern2,但左方不能为 Pattern1
    ex: (?<!Chapter|Section)(?<!\d)[\d]+ 可符合 Topic15 的 15,但不符合 Chapter15 的 15

说明:

  1. 以上判断式的小括号 (? ... ) 并不会成为“群组”
  2. 并非所有的环境都能完整支援判断式的用法

线上测试

  1. Regular Expressions 101
  2. RegEx Testing
  3. 正规表示式线上测试-站长工具
  4. Regulex: JavaScript Regular Expression Visualizer - 将正规表示式图形化
  5. Regexper - 将正规表示式图形化
  6. 编程胶囊 - 教学与题目练习
  7. RegexOne - 题目练习

参考网页

  1. 正规表示式 - 维基百科,自由的百科全书
  2. [转载]PHP 正规表示式基本语法
  1. No comments yet.

  1. No trackbacks yet.

return top

%d 位部落客按了赞: