在一个捕获组上使用负回顾后断言

7
我正在尝试编写一些正则表达式,以便在电子邮件中提取可能的引用。我需要知道如何从特定位置向后查找到第一个空格。如果找到数字,则不希望提取引用。我已经完成了以下工作。我有两个捕获组——“PreRef”和“Ref”。如果“PreRef”包含数字,则不希望找到“Ref”匹配项。到目前为止,我只检查冒号之前的字符是否是数字。
(?<PreRef>\S+)(?<![\d]):(?<Ref>\d{5})

这里应该找到一个编号为12345的'Ref'匹配项:

This is a reference:12345

但是这里不行(单词“reference”中有一个数字5):
This is not a ref5rence:12345

1
什么是编程语言? - Wiktor Stribiżew
3个回答

3
您可以从\S类中排除数字,然后在表达式周围加上空格边界,然后就完成了......

(?<!\S)(?<PreRef>[^\s\d]+):(?<Ref>\d{5})(?!\S)

https://regex101.com/r/JrU7Kd/1

解释:

 (?<! \S )                     # Whitespace boundary
 (?<PreRef> [^\s\d]+ )         # (1), Not whitespace nor digit
 :                             # Colon
 (?<Ref> \d{5} )               # (2), Five digits
 (?! \S )                      # Whitespace boundary

2
你需要负向回顾吗?从PreRef捕获中排除数字会更容易。 [^\W\d]将匹配单词字符但不匹配数字。然后,您只需要添加一个\b或其他类似的单词边界断言,以确保匹配的是完整的单词。"最初的回答"
\b(?<PreRef>[^\W\d]+):(?<Ref>\d{5})

“[^\s\d]”比“[^\W\d]”更合适吗?因为OP在问题中使用了“\S”。 - 3limin4t0r
使用\s需要比\b更复杂的零宽断言,因为\b检查单词到非单词的转换。 - John Kugelman

1

我完全同意John的观点,我们可以使用一个简单的表达式,如果不允许在:之前输入数字,例如:

^\D+:(\d{5})

或者:

^\D+:(\d{5})$

如果我们希望添加更多的边界,那么我们肯定也可以这样做。

演示

正则表达式电路

jex.im 可视化正则表达式:

enter image description here

测试

const regex = /^\D+:(\d{5})/gm;
const str = `This is a reference:12345
This is not a ref5rence:12345`;
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}`);
    });
}


1
这个解决方案对我来说并不完全适用,因为它会阻止在引用之前有任何数字的情况下提取引用,例如在句子早期,比如“这是1个引用:12345”。 - Lank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接