正则表达式可选单词匹配


76

我正在尝试创建一个用于提取歌手,歌词作者的正则表达式。我想知道如何使歌词作者搜索成为可选项。

示例多行字符串:

Fireworks Singer: Katy Perry
Vogue Singers: Madonna, Karen Lyricist: Madonna

正则表达式: /Singers?:(.\*)\s?Lyricists?:(.\*)/

这与第二行正确匹配,并提取Singers(Madonna, Karen)Lyricists(Madonna)

但是,当没有抒情诗人时,它不适用于第一行。

如何使歌词搜索成为可选内容?

Answers:


117

您可以将要匹配的部分包含在一个非捕获组中:(?:)。然后可以将其视为正则表达式中的单个单元,随后可以?在其后放置a以使其成为可选。例:

/Singers?:(.*)\s?(?:Lyricists?:(.*))?/

请注意,这里\s?没用,因为.*它将贪婪地吞噬所有字符,因此无需回溯。这也意味着,(?:Lyricists?:(.*))出于相同的原因,该零件将永远不会被匹配。您可以使用的非贪婪版本.*.*?伴随着$解决这个问题:

/Singers?:(.*?)\s*(?:Lyricists?:(.*))?$/

一些多余的空格最终被捕获;也可以将其删除,得到最终的正则表达式:

/Singers?:\s*(.*?)\s*(?:Lyricists?:\s*(.*))?$/

使用匹配的模式($1$2...)如何将嵌套括号也通过数字引用?
2012年

@puk:我不确定我是否理解您的问题。(?:)是一个非捕获组,这意味着它们匹配的任何内容都无法通过引用$1,等等。()是一个捕获组,这意味着它们匹配的任何内容都可以通过捕获,并通过$1等获得。如果您有嵌套的(())组,则最外面的一个是$1,内部的将是$2,等等(这仍然遵循正常的从左到右的规则;左(括号是确定哪个组获得哪个数字)。
卡梅伦

这样的回答我的问题,我想知道一些(([a-z]{32})?):(([0-9]{32})?)可选的用户名:id double。如果我运行的字符串":"都将$1$2空?那"john:"呢 是否有$3$4
2012年

1
@puk:嗯,让我们看看。最好和最快的方法是通过正则表达式测试器运行该程序(或使用特定的正则表达式引擎编写您自己的测试)。但是,让我对此付诸行动。你有四个小组。对于':',组1和3具有空字符串的值,因为它们匹配其中的所有内容(即可选内容)。第2组和第4组(后跟的组?)是undefined / null / empty-string,具体取决于语言/正则表达式引擎。您可以将正则表达式简化为2个组:([a-z]{32})?:([0-9]{32})?或使用非捕获组:((?:[a-z]{32})?):((?:[0-9]{32})?)
卡梅伦

1
re.compile(r'(。*)(?: SKIPPED?)(?: PASSED?)(?: FAILED?)')是否可以使用上述表达式来选择性地搜索SKIPPED /PASSED/Failed....and其中之一必须在场
Ravi Yadav

0

只是为了添加Cameron的解决方案。如果源字符串有多行,每行同时包含歌手和抒情诗,则可能需要添加'm'多行修饰符,以使'$'与行尾匹配。(您没有说您使用的是哪种语言-您可能还想添加'i'修饰符。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.