我希望使用正则表达式模式H-\d{4}
捕获整行,以及(可选)ID,例如H-1234
。
这是两个样本行,一个带ID,另一个没有ID:
带有H-5722 id的样品行
没有ID的示例行
在第一个ALL中应该捕获整行,ID H-5722。在第二个ALL中应捕获整行,ID应为空。
这个正则表达式适用于第一行,捕获ALL和ID:
^(?<ALL>.*?(?<ID>H-\d{4})\b.*)$
但是它没有像预期的那样匹配第二行,因为它没有ID。
因此,我尝试使用?
零或一修饰符(?:(?<ID>H-\d{4}))?
的非捕获组使ID捕获成为可选项,或者修改ID组以便它可以捕获表达式或空字符串(?<ID>H-\d{4}|)
:
^(?<ALL>.*?(?:(?<ID>H-\d{4})\b)?.*)$
^(?<ALL>.*?(?<ID>H-\d{4}|)\b.*)$
通过这些修改,ALL捕获了两个示例中的整行。但它并没有捕获ID。
我怎样才能做到这一点?
我使用.NET正则表达式实现,但我认为它与其他实现非常相似。
答案 0 :(得分:1)
使用替换:
^(?<ALL>(?!.*H-\d{4}\b).*|.*?(?:(?<ID>H-\d{4})\b).*)$
请参阅https://regex101.com/r/dZx3b1/1/
或者使用unrolled tempered greedy token(表现)
^(?<ALL>[^H\n]*(?:H(?!-\d{4}\b)[^H\n]*)*(?<ID>H-\d{4}\b)?.*)$
请参阅https://regex101.com/r/9ILEhw/1/
基本上强制使用ID组,如果可以找到它。
您的方法失败,因为.*?
始终与初始空字符串匹配,跳过可选的ID模式,.*
与实际字符串匹配。
答案 1 :(得分:1)
在.NET
中,您可以使用
(?:(?<ALL>.*(?<ID>\bH-\d{4}\b).*)|(?<ALL>.+))
见a working demo on regex101.com。
<小时/> 细分,这说:
(?: # open non-capturing group
(?<ALL>.*(?<ID>\bH-\d{4}\b).*) # with ID
| # or
(?<ALL>.+) # without ID
)
无论您的内容是什么,ALL
都会保留完整的行,ID
只有在H-1234
形式的ID确实存在时才会出现。正如评论中所述,这只能在.NET
(see here on SO)中使用,并且与PCRE
之类的语法无效。
答案 2 :(得分:1)
答案 3 :(得分:0)
以下模式似乎有效:
^((?:(?!H-\d{4}).)*(H-\d{4})?\b.*)$
在存在H
想法的情况下,它将在第二个捕获组中可用。如果不是,则第二个捕获组将为空。在任何一种情况下,整个字符串都会出现在第一个捕获组中。
string input = "Sample line with H-123 id";
Regex r1 = new Regex(@"^((?:(?!H-\d{4}).)*(H-\d{4})?\b.*)$");
Match match = r1.Match(input);
if (match.Success)
{
Console.WriteLine("First capture group: {0}", match.Groups[1].Value);
Console.WriteLine("Second capture group: {0}", match.Groups[2].Value);
}