regex - 学习正则表达式

标签 regex

就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the help center为指导。




9年前关闭。










这个问题的答案是community effort .编辑现有答案以改进这篇文章。它目前不接受新的答案或互动。








我真的不明白正则表达式。你能用一种易于理解的方式向我解释它们吗?如果有任何在线工具或书籍,您是否也可以链接到它们?

最佳答案

最重要的部分是概念。一旦您了解了构建块的工作原理,语法上的差异就只不过是温和的方言而已。正则表达式引擎语法之上的一层是您正在使用的编程语言的语法。 Perl 等语言消除了大部分这种复杂性,但如果您在 C 程序中使用正则表达式,则必须牢记其他注意事项。

如果您将正则表达式视为可以随意混合和匹配的构建块,它可以帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。

开始简单

从概念上讲,最简单的正则表达式是文字字符。模式 N 匹配字符“N”。

彼此相邻的正则表达式匹配序列。例如,模式 Nick 匹配序列 'N' 后跟 'i' 后跟 'c' 后跟 'k'。

如果你曾经在 Unix 上使用过 grep——即使只是为了搜索普通的字符串——你已经在使用正则表达式了! (re 中的 grep 指的是正则表达式。)

从菜单订购

添加一点复杂性,您可以将 'Nick' 或 'nick' 与模式 [Nn]ick 匹配。方括号中的部分是一个字符类,这意味着它与封闭字符中的一个完全匹配。您还可以在字符类中使用范围,因此 [a-c] 匹配“a”或“b”或“c”。
. 模式很特殊:它不只匹配文字点,而是匹配任何字符†。它在概念上与真正的大字符类 [-.?+%$A-Za-z0-9...] 相同。

将字符类视为菜单:只选择一个。

有用的快捷键

使用 . 可以为您节省大量输入,并且还有其他常见模式的快捷方式。假设你想匹配一个数字:一种写法是 [0-9] 。数字是频繁匹配的目标,因此您可以改用快捷方式 \d 。其他是 \s(空格)和 \w(单词字符:字母数字或下划线)。

例如,大写变体是它们的补码,因此 \S 匹配任何非空白字符。

一次还不够

从那里,您可以使用量词重复部分模式。例如,模式 ab?c 匹配 'abc' 或 'ac',因为 ? 量词使其修改的子模式成为可选的。其他量词是

  • *(零次或多次)
  • +(一次或多次)
  • {n}(正好 n 次)
  • {n,}(至少 n 次)
  • {n,m}(至少n次但不超过m次)

  • 将这些块中的一些放在一起,模式 [Nn]*ick 匹配所有
  • ick
  • 尼克
  • 昵称
  • 尼克
  • 尼克
  • 尼克
  • (等等)

  • 第一场比赛展示了一个重要的教训:* 总是成功的!任何模式都可以匹配零次。

    其他一些有用的例子:
  • [0-9]+ (及其等效的 \d+ )匹配任何非负整数
  • \d{4}-\d{2}-\d{2} 匹配格式为 2019-01-01
  • 的日期

    分组

    量词修改其左边的模式。您可能希望 0abc+0 与 '0abc0'、'0abcabc0' 等匹配,但紧靠加量词左侧的模式是 c 。这意味着 0abc+0 匹配“0abc0”、“0abcc0”、“0abccc0”等。

    要将一个或多个 'abc' 序列与末尾的零匹配,请使用 0(abc)+0 。括号表示可以量化为一个单位的子模式。正则表达式引擎保存或“捕获”与括号组匹配的输入文本部分也很常见。以这种方式提取位比计数索引和 substr 更灵活且不易出错。

    交替

    早些时候,我们看到了一种匹配“尼克”或“尼克”的方法。另一个是与 Nick|nick 中的交替。请记住,交替包括其左侧的所有内容和其右侧的所有内容。使用分组括号来限制 | 的范围,例如 (Nick|nick)

    再举一个例子,你可以等效地将 [a-c] 写成 a|b|c ,但这可能不是最理想的,因为许多实现假设替代品的长度大于 1。

    逃跑

    虽然有些字符与自己匹配,但其他字符具有特殊含义。模式 \d+ 不匹配反斜杠后跟小写 D 后跟加号:要得到它,我们将使用 \\d\+ 。反斜杠删除以下字符的特殊含义。

    贪婪

    正则表达式量词是贪婪的。这意味着它们匹配尽可能多的文本,同时允许整个模式成功匹配。

    例如,假设输入是

    "Hello," she said, "How are you?"



    您可能期望 ".+" 只匹配 'Hello',然后当您看到它从 'Hello' 一直匹配到 'you?' 时会感到惊讶。

    要从贪婪切换到您可能认为的谨慎,请向量词添加额外的 ?。现在您了解 \((.+?)\) ,您问题中的示例是如何工作的。它匹配文字左括号的序列,后跟一个或多个字符,并以右括号终止。

    如果您的输入是“(123) (456)”,则第一次捕获将是“123”。非贪婪量词希望允许模式的其余部分尽快开始匹配。

    (至于你的困惑,我不知道 ((.+?)) 会做同样事情的任何正则表达式方言。我怀疑在传输过程中的某个地方丢失了一些东西。)

    anchor

    使用特殊模式 ^ 仅在输入的开头匹配,使用 $ 仅在结尾匹配。用你的图案制作“书挡”,你说“我知道正面和背面是什么,但给我之间的一切”是一种有用的技术。

    假设您要匹配表单的评论

    -- This is a comment --



    你会写 ^--\s+(.+)\s+--$

    建立你自己的

    正则表达式是递归的,所以现在您了解了这些基本规则,您可以随意组合它们。

    用于编写和调试正则表达式的工具:
  • RegExr(用于 JavaScript)
  • Perl:YAPE: Regex Explain
  • Regex Coach(由 CL-PPCRE 支持的引擎)
  • RegexPal(用于 JavaScript)
  • Regular Expressions Online Tester
  • Regex Buddy
  • Regex 101(用于 PCRE、JavaScript、Python、Golang)
  • Visual RegExp
  • Expresso(用于.NET)
  • Rubular(用于 Ruby)
  • Regular Expression Library(常见场景的预定义正则表达式)
  • Txt2RE
  • Regex Tester(用于 JavaScript)
  • Regex Storm(用于.NET)
  • Debuggex(视觉正则表达式测试器和助手)

  • 书籍
  • Mastering Regular Expressions2nd Edition3rd edition
  • Regular Expressions Cheat Sheet
  • Regex Cookbook
  • Teach Yourself Regular Expressions

  • 免费资源
  • RegexOne - Learn with simple, interactive exercises.
  • Regular Expressions - Everything you should know (PDF 系列)
  • Regex Syntax Summary
  • How Regexes Work

  • 脚注

    †: 上面关于 . 匹配任何字符的陈述是出于教学目的的简化,并非严格正确。点匹配除换行符 "\n" 之外的任何字符,但在实践中,您很少期望像 .+ 这样的模式跨越换行符边界。 Perl 正则表达式有一个 /s switch 和 Java Pattern.DOTALL ,例如,使 . 匹配任何字符。对于没有这种特性的语言,你可以使用类似 [\s\S] 的东西来匹配“任何空白或任何非空白”,换句话说任何东西。

    关于regex - 学习正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4736/

    相关文章:

    php - 仅字母的 laravel 验证规则

    javascript - 如何简化此正则表达式来选择 Blogger 图像参数?

    ios - 如何在iOS sdk中使用正则表达式

    r - 小写某些单词 R

    正则表达式模式不支持 # 符号

    regex - CIDR 表示法中 IPV6 地址的正则表达式

    Javascript正则表达式忽略第一个捕获组

    javascript - 使用带有正则表达式的拆分不能正确替换?

    c# - 正则表达式匹配不正确的值

    javascript - 在文本字符串中查找与 Twitter 使用完全相同的任何 URL