正则表达式匹配用括号括起来并用管道分隔的所有单词

Posted

技术标签:

【中文标题】正则表达式匹配用括号括起来并用管道分隔的所有单词【英文标题】:Regex match all words enclosed by parentheses and separated by a pipe 【发布时间】:2021-12-08 20:01:03 【问题描述】:

我认为有时图像比文字更好。

如您所见,我的问题是它只匹配两个单词。如何匹配所有单词?

我当前的正则表达式(PCRE):([^\|\(\)\|]+)\|([^\|\(\)\|]+)

目标:为每个单词检索单独分组中的所有单词

【问题讨论】:

所以它应该匹配fish?这就是问题所在? 抱歉不够清楚。它应该匹配所有的单词,直到 prenthese 结束。 【参考方案1】:

您可以在 C# 中使用无限长的lookbehind(带有lookahead):

(?<=\([^()]*)\w+(?=[^()]*\))

要匹配括号内不包含()| 的任何类型的字符串,您需要将\w+ 替换为[^()|]+

(?<=\([^()]*)[^()|]+(?=[^()]*\))
//            ^^^^^^

参见regex demo(和regex demo #2)。 详情

(?&lt;=\([^()]*) - 一个正向的后视,匹配紧接在( 前面的位置,然后是() 以外的零个或多个字符 \w+ - 一个或多个单词字符 (?=[^()]*\)) - 一个正向前瞻,它匹配一个紧跟零个或多个字符的位置,而不是 (),然后是 ) 字符。

捕捉这些词的另一种方法是使用

(?:\G(?!^)\||\()(\w+)(?=[^()]*\))     // words as units consisting of letters/digits/diacritics/connector punctuation
(?:\G(?!^)\||\()([^()|]+)(?=[^()]*\)) // "words" that consist of any chars other than (, ) and |

见this regex demo。您需要的单词现在在第 1 组中。详细信息

(?:\G(?!^)\||\() - 上一场比赛之后的位置 (\G(?!^)) 和 | 字符 (\|),或 (|) ( 字符 (\() (\w+) - 第 1 组:一个或多个单词字符 (?=[^()]*\)) - 正向前瞻,确保在当前位置右侧除() 之外的任何零个或多个字符之后都有一个) 字符。

在 C# 中提取匹配项可以使用

var matches = Regex.Matches(text, @"(?<=\([^()]*)\w+(?=[^()]*\))")
    .Cast<Match>()
    .Select(x => x.Value);

// Or
var matches = Regex.Matches(text, @"(?:\G(?!^)\||\()(\w+)(?=[^()]*\))")
    .Cast<Match>()
    .Select(x => x.Groups[1].Value);

【讨论】:

这很酷,因为它甚至可以与其他分隔符匹配单词。但是(?&lt;=[(|])\w+(?=[|)]) 不是更简单,更适合 OP 的需求吗? 我无法期待更好。优秀 !非常感谢,这正是我想要的? @Keytrap 欢迎您。另外,这里是C# demo。 Sorry 刚刚发现一个小错误(我没有提到这个抱歉),即使单词中有空格,它也能匹配单词吗?例如 (first|second|third and Fourth) 将是 first second third and fourth ? @Keytrap 将\w+ 替换为[^()|]+【参考方案2】:

在 c# 中,您还可以使用捕获组来使用组捕获。

匹配在命名组word

\((?<word>\w+)(?:\|(?<word>\w+))*\)
\(匹配( (?&lt;word&gt;\w+) 匹配组中的 1+ 个单词字符 word (?:非捕获组 \|匹配| (?&lt;word&gt;\w+) 匹配 1+ 个单词字符 )* 关闭非捕获组并可选择重复以获取所有事件 \) 匹配右括号

Wiktor Stribiżew 在 cmets 中提供的代码示例:

var line = "I love (chocolate|fish|honey|more)";
var output = Regex.Matches(line, @"\((?<word>\w+)(?:\|(?<word>\w+))*\)")
    .Cast<Match>()
    .SelectMany(x => x.Groups["word"].Captures);
foreach (var s in output)
        Console.WriteLine(s);

输出

chocolate
fish
honey
more

foreach(输出中的 var s) Console.WriteLine(s);

Regex demo

【讨论】:

不幸的是,当单词 a 被管道分隔并且所有单词都被括号括起来但它不会分隔组中的每个单词时,这匹配。 @Wiktor 的答案是正确的。无论如何,谢谢你的时间:) @Keytrap 你只需要获取每个捕获值所在的CaptureCollection (match.Groups["word"].Captures)。见the C# demo。这也是一个可以在 C# 中使用的有效解决方案。 @Thefourthbird 你可能可以创建一个更好的演示,我不认为我现在“煮”的那个是最好的,只是想表明这种方法有效。 @Thefourthbird 我在原始链接中简化了代码。 Regex.Matches(line, @"\((?&lt;word&gt;\w+)(?:\|(?&lt;word&gt;\w+))*\)").Cast&lt;Match&gt;().Select(x =&gt; x.Groups["word"].Captures) 就够了。 @Thefourthbird 对,.SelectMany 获取展平项目。我们不知道这里的确切情况,所以任何人都可以。

以上是关于正则表达式匹配用括号括起来并用管道分隔的所有单词的主要内容,如果未能解决你的问题,请参考以下文章

Hive正则表达式

正则表达式(re)

Python正则表达式之 - ?: / ?= / ?!

小白的正则表达式的学习之旅-03

C#正则表达式匹配方括号

正则表达式 第三篇:分组匹配