给定以下文本:
somerandomtext06251/750/somerandomtext/21399/10 79/20 8301
如何提取 06251/750、79/20、8301 并忽略 21399/10 ?
一般规则:
- 在随机字符串中,匹配每组至少 2 位数字,后跟可选/和另一个至少 2 位数字;对数字保持贪婪(尽可能多地获取(
- 如果完全匹配前面紧跟/
我从以下匹配模式开始:
(?<invnr>d{2,}/?d{2,})
一般来说,它可以工作,但它只有一个问题:它也需要 21399/10。所以,我加了一个负面的回望:
(?<!/)(?<invnr>d{2,}/?d{2,})
现在它忽略了 21399/10 的第一个数字(因为它前面有/(,但它仍然捕获了以下所有字符,即 1399/10。但是我需要完全跳过 21399/10。
如何进行回溯以删除整个匹配并跳到下一个匹配而不是只跳过一位数字?
您可以在负后视中添加数字模式(通过使用字符类[/d]
将其与/
组合(,以确保如果紧跟在数字之后,则不会发生匹配:
(?<![/d])d{2,}(?:/d{2,})?
查看正则表达式演示
详
(?<![/d])
- 如果当前位置左侧有/
或数字,则匹配失败的负回溯d{2,}
- 两位或更多位数(?:/d{2,})?
- 一个/
和两个或更多数字的可选序列。
如果需要确保仅匹配 ASCII 数字,请将RegexOptions.ECMAScript
选项传递给 .NET 方法中的正则表达式编译器,或使用[0-9]
而不是d
。
请注意,您的d{2,}/?d{2,}
有点不对劲,因为它不会匹配 2 位或 3 位序列,而只会匹配 4+ 位序列。
尽管不如Wiktor的答案那么强大,但您可以选择在模式之前提供允许字符的白名单:
(?<=^|[ a-z])[0-9]{2,}(?:/[0-9]{2,})?
正则表达式演示
另一种方法是匹配以/
开头的模式,并使用交替|
捕获那些不在组中()
的模式。
/[0-9]{2,}(?:/[0-9]{2,})?|(?<invnr>[0-9]+(?:/[0-9]{2,})?)
/[0-9]{2,}(?:/[0-9]{2,})?
将模式与前导/
匹配|
或(?<invnr>[0-9]+(?:/[0-9]{2,})?)
捕获组中的模式 invnr
.NET 正则表达式演示(单击"表"选项卡以查看组值(