如何简化正则表达式模式?

How to simplify a regex pattern?

我在这里试图简化正则表达式。

我尝试对同一个表达式进行重复,但是当我尝试使用 ()* 简化它时,它不起作用,因为它没有检测到我想要的模式。

这些是我的正则表达式:

(([\(]\w]{1,3}[\)])\s([\d]{1,3}[\?])([\(][\w]{1,3}[\)])\s[\d]{1,3}[\?]([\(][\w]{1,3}[\)])\s([\d]{1,3}[\?])([\(][\w]{1,3}[\)])\s[\d]{1,3}[\?]([\(][\w]{1,3}[\)])\s[0-9]{1,3}[\?]([\(][\w]{1,3}[\)])\s[\d]{1,3}[\?])

整个模式:

3A 1?(1) 2?(2) 3?(a) 4?(4) 5?(a) 6?(ii) 7?
4 6?(1) 7?(2) 8?(a) 9?(4) 10?(a) 11?(ii) 12?  

这些是它将检测到的模式:

1?(1) 2?(2) 3?(a) 4?(4) 5?(a) 6?(ii) 7?

正则表达式将检测 ONLY first LINE 而没有 3A。我该怎么做? 正则表达式已经是最简单的 \d+\?(?:\([\da-z]+\))? ,现在我怎样才能把它放在一种只检测 第一行 的方式中?谢谢大家。

也许,如果可能的话,我们可以用另一种方式简化它。例如,我们可能有三个模式,我们可以使用三个捕获组来捕获它:开始、结束和中间组,可能类似于:

(?:^\w+\s)|(\d\?\(\w+\)\s)|(?:\d+\?$)

正则表达式

如果这不是您想要的表达式,您可以 modify/change 在 regex101.com 中添加您的表达式,并根据需要添加或减少边界。

正则表达式电路

您还可以在 jex.im:

中可视化您的表情

JavaScript 捕获组演示

const regex = /(?:^\w+\s)|(\d\?\(\w+\)\s)|(?:\d+\?$)/gm;
const str = `3A 4?(1) 5?(2) 6?(a) 7?(4) 8?(a) 9?(ii) 10?`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

此模式 ([\(][\w]{1,3}[\)])\s[\d]{1,3}[\?] 与前导 4?

不匹配

您可以通过删除方括号来简化表达式,因为您不需要它们并添加一个可选部分以匹配前面带问号的 1-3 位数字:

(?:\d{1,3}\?)?(\(\w{1,3}\))\s\d{1,3}\?

Regex demo

如果您不想要单独的匹配,而是 1 个单独的匹配,并且数字问号部分也可以在括号之间没有以下部分的情况下出现,您可以使用一个重复组和一个可选部分作为括号:

\d+\?(?:\(\w{1,3}\))?(?: \d+\?(?:\(\w{1,3}\))?)+

说明

  • \d+\?匹配1+个数字和?
  • (?:\(\w{1,3}\))? 匹配括号部分的可选组
  • (?:非捕获组
    • \d+\?(?:\(\w{1,3}\))? 匹配 1+ 个数字和 ? 后跟括号的可选部分
  • )+关闭非捕获组并重复1+次

Regex demo

备注

在您的示例的第一个模式中缺少左括号

(([\(][\w]{1,3}
      ^ 

在第二个表达式中,模式末尾有一个右括号 )

试试这个模式:\d+\?(?:\([\da-z]+\))?

解释:

\d+ - 匹配一位或多位数字

\? - 按字面意思匹配 ?

(?:...) - non-capturing组

\( - 按字面意思匹配 (

[\da-z]+ - 匹配一个或多个数字或小写字母

\) - 按字面意思匹配 )

? - 最多匹配一次前面的模式,即 \([\da-z]+\)

Demo

代码中的用法:

Sub Main()
    Dim matches = Regex.Matches("3A 4?(1) 5?(2) 6?(a) 7?(4) 8?(a) 9?(ii) 10?", "\d+\?(?:\([\da-z]+\))?")
    For Each match As Match In matches
        Console.WriteLine(match.Value)
    Next
    Console.ReadKey()
End Sub

更新:

尝试更新模式:^(?:\d+(?:\?(?:\([\da-z]+\))?|[A-Z]+) ?)+$

Demo