学习正则expression式
我不太了解正则expression式。 你能以简单易懂的方式向我解释吗? 如果有任何在线工具或书籍,您是否也可以链接到它们?
最重要的部分是概念。 一旦你理解了这些积木是如何工作的,语法上的差异只不过是轻度的方言而已。 正则expression式引擎语法之上的一个层是您正在使用的编程语言的语法。 像Perl这样的语言除去了大部分的复杂性,但是如果你在C程序中使用正则expression式的话,你必须记住其他的注意事项。
如果将正则expression式看作是可以随意混搭的构build块,则可以帮助您学习如何编写和debugging自己的模式,以及如何理解其他模式。
开始简单
从概念上讲,最简单的正则expression式是文字字符。 模式N
匹配字符“N”。
彼此相邻的正则expression式匹配序列。 例如,模式Nick
匹配序列“N”,接着是“i”,接着是“c”,接着是“k”。
如果你曾经在Unix上使用过grep
,即使只是寻找普通的string,你已经使用了正则expression式! ( grep
的re
是指正则expression式。)
从菜单中订购
只增加一点复杂性,就可以将'Nick'或'nick'与模式[Nn]ick
匹配。 方括号中的部分是一个字符类 ,这意味着它恰好匹配一个封闭的字符。 您还可以在字符类中使用范围,因此[ac]
匹配“a”或“b”或“c”。
模式.
是特殊的:不是只匹配一个字面点,而是匹配任何字符† 。 在概念上和真正的大字符类一样[-.?+%$A-Za-z0-9...]
。
把angular色类看作菜单:只选一个。
有用的捷径
使用.
可以为您节省大量的input,并且还有其他常见模式的快捷方式。 假设你想匹配非负整数:写一个方法是[0-9]+
。 数字是一个频繁的匹配目标,所以你可以使用\d+
匹配非负整数。 其他是(空格)和\w
(单词字符:字母数字或下划线)。
大写的变体是它们的补充,所以\S
匹配任何非空白字符,例如。
一次是不够的
从那里,你可以用量词重复你的模式的一部分。 例如,abc模式匹配“abc”或“ac”,因为?
量词使得它修改的子模式是可选的。 其他量词是
-
*
(零次或多次) -
+
(一次或多次) -
{n}
(正好n次) -
{n,}
(至lessn次) -
{n,m}
(至lessn次,但不多于m次)
把这些块放在一起,模式[Nn]*ick
匹配全部
- ICK
- 缺口
- 缺口
- Nnick
- nNick
- nnick
- (等等)
第一场比赛展示了一个重要的教训: *
总是成功! 任何模式都可以匹配零次。
分组
量词将模式修改为其左侧。 您可能期望0abc+0
匹配“0abc0”,“0abcabc0”等,但加号量词左侧的模式为c
。 这意味着0abc+0
与“0abc0”,“0abcc0”,“0abccc0”匹配,依此类推。
要匹配一个或多个'abc'序列与末尾的零,请使用0(abc)+0
。 括号表示可以量化为一个单位的子模式。 正则expression式引擎保存或“捕获”与加括号的组相匹配的input文本部分也很常见。 以这种方式提取位比计数索引和substr
更灵活,更不容易出错。
轮stream
早些时候,我们看到了一种匹配“尼克”或“尼克”的方法。 另一个是在Nick|nick
交替。 请记住,交替包括左侧的一切,右侧的一切。 使用分组括号来限制|
的范围 , 例如 (Nick|nick)
。
再举一个例子,你可以等价地把[ac]
写成a|b|c
,但是这可能是次优的,因为许多实现假定备选将具有大于1的长度。
逃离
虽然有些人物相配,但其他人则有特殊的意义。 模式\d+
不匹配反斜杠,接着是小写字母D,后跟一个加号:为了得到这个,我们使用\\d\+
。 反斜杠从以下字符中删除特殊含义。
贪婪
正则expression式量词是贪婪的。 这意味着它们匹配尽可能多的文本,同时允许整个模式匹配成功。
例如,说input是
“你好,”她说,“你好吗?
你可能会希望".+"
只匹配“你好”,当你看到从“你好”到“你”的匹配时,你会感到惊讶。
要从贪婪切换到您可能认为谨慎的地方,请添加额外的?
量词。 现在你明白\((.+?)\)
,你的问题的例子是如何工作的。 它匹配文字左括号的序列,后跟一个或多个字符,并以右括号结束。
如果你的input是'(123)(456)',那么第一个捕获将是'123'。 非贪婪量词希望允许模式的其余部分尽快开始匹配。
(至于你的困惑,我不知道任何正则expression方言((.+?))
会做同样的事情,我怀疑在传播过程中有什么东西丢失了。
锚
使用特殊模式^
仅在input开始时匹配, $
仅在最后匹配。 用你说的“你知道什么是在前面和后面,但是给我所有的东西”来形成“书挡”是一种有用的技巧。
假设你想匹配表单的评论
-- This is a comment --
你会写^--\s+(.+)\s+--$
。
build立你自己的
正则expression式是recursion的,所以现在你明白了这些基本规则,不pipe你喜欢什么,都可以把它们组合起来。
编写和debugging正则expression式的工具:
- RegExr (用于JavaScript)
- Perl: YAPE:正则expression式解释
- 正规 教练 ( CL-PPCRE支持的引擎)
- 正则expression式 (适用于JavaScript)
- 正则expression式在线testing器
- 正则expression式好友
- 正则expression式101 (PCRE,JavaScript,Python,Golang)
- 可视化RegExp
- Expresso (用于.NET)
- Rubular (ruby)
- 正则expression式库 (用于常见场景的预定义正则expression式 )
- Txt2RE
- 正则expression式testing器 (适用于JavaScript)
- 正则expression式风暴 (.NET)
图书
- 掌握正则expression式 , 第二版和第三版 。
- 正则expression式备忘录
- 正则expression式食谱
- 教你自己的正则expression式
免费资源
- 正则expression式 – 你应该知道的一切 (PDF系列)
- 正则expression式语法摘要
- 正则expression式的工作原理
脚注
†:上面的陈述.
匹配任何字符是一个简化的教学目的,这是不严格的。 点匹配除换行符"\n"
以外的任何字符,但在实践中,您很less会期望诸如.+
类的模式跨过换行符边界。 例如Perl正则expression式有一个/s
开关和Java Pattern.DOTALL
.
匹配任何字符。 对于没有这种function的语言,可以使用类似[\s\S]
来匹配“任何空格或任何非空格”,换句话说就是任何东西。