关于正则表达式:学习正则表达式

关于正则表达式:学习正则表达式

Learning Regular Expressions

我不太了解正则表达式。 您能以一种易于理解的方式向我解释它们吗? 如果有任何在线工具或书籍,您还可以链接到它们吗?


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

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

从简单开始

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

正则表达式彼此相邻,匹配序列。例如,模式Nick与序列" N"," i"," c"," k"匹配。

如果您曾经在Unix上使用grep-即使仅用于搜索普通的字符串-您已经在使用正则表达式! (grep中的re引用正则表达式。)

从菜单订购

稍微增加一点复杂性,您就可以将'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
  • 缺口
  • 缺口
  • Nnick
  • nNick
  • nnick
  • (等等)
  • 第一场比赛展示了一个重要的教训:*总是成功!任何模式都可以匹配零次。

    其他一些有用的例子:

  • [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?"

    Ok.

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

    要从贪婪转向谨慎,可以在量词上添加一个额外的?。现在您了解了问题示例中的\((.+?)\)的工作原理。它与文字左括号的顺序匹配,后接一个或多个字符,并以右括号终止。

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

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

    使用特殊模式^仅在输入的开头进行匹配,而$仅在输入的末尾进行匹配。用您的模式制作"书挡",您说:"我知道正面和背面是什么,但是请给我之间的一切"是一种有用的技术。

    假设您要匹配表单的注释

    -- This is a comment --

    Ok.

    您将编写^--\s+(.+)\s+--$

    建立你自己的

    正则表达式是递归的,因此,既然您了解了这些基本规则,就可以随意组合它们。

    编写和调试正则表达式的工具:

  • RegExr(用于JavaScript)
  • Perl:YAPE:Regex解释
  • 正则表达式教练(由CL-PPCRE支持的引擎)
  • RegexPal(用于JavaScript)
  • 正则表达式在线测试器
  • 正则表达式好友
  • 正则表达式101(用于PCRE,JavaScript,Python,Golang)
  • 视觉正则表达式
  • Expresso(用于.NET)
  • Rubular(对于Ruby)
  • 正则表达式库(常见方案的预定义正则表达式)
  • Txt2RE
  • 正则表达式测试器(用于JavaScript)
  • 正则表达式风暴(.NET)
  • Debuggex(可视化正则表达式测试器和帮助器)
  • 图书

  • 精通正则表达式,第二版和第三版。
  • 正则表达式备忘单
  • 正则表达式食谱
  • 教自己正则表达式
  • 免费资源

  • RegexOne-通过简单的交互式练习学习。
  • 正则表达式-您应该知道的一切(PDF系列)
  • 正则表达式语法摘要
  • 正则表达式如何工作
  • 脚注

    ?:上面的.匹配任何字符的陈述是出于教学目的的简化,并非严格如此。点匹配除换行符"
    "
    以外的任何字符,但实际上,您很少期望像.+这样的图案跨越换行符边界。 Perl正则表达式具有/s开关和Java Pattern.DOTALL,例如,使.完全匹配任何字符。对于没有这种功能的语言,可以使用[\s\S]之类的东西来匹配"任何空白或任何非空白",换句话说,就是任何东西。

    好。


    推荐阅读