【发布时间】:2021-07-13 14:17:38
【问题描述】:
如果我有一个字符串并希望捕获一个可能为空的字符串(然后检查它是否确实为空),我该怎么做?当捕获的部分不为空时,我的正则表达式有效,并且在第一印象中,它似乎在字符串为空的情况下有效,因为Console.WriteLine(second); 不产生任何输出。
string notEmpty = "abc|CaptureMeButICanBeEmpty|def";
string isEmpty = "abc||def";
string regEx = @"^\w+\|([^|]+|)\|\w+$";
var match = Regex.Match(notEmpty, regEx);
var match2 = Regex.Match(isEmpty, regEx);
string first = match.Groups[1].Value;
Console.WriteLine(first); // CaptureMeButICanBeEmpty
string second = match2.Groups[1].Value;
Console.WriteLine(second); // No Output
Console.WriteLine(match.Groups.Count); // 2
Console.WriteLine(match2.Groups.Count); // 2
但是,不可能知道second 是否为空因为捕获组为空,或者仅仅是因为根本没有第二个捕获组。
也就是说:
string third = match2.Groups[2].Value;
Console.WriteLine(second); // No Output
也不会产生任何输出,因为捕获组不存在,并且使用类似的东西进行测试
Console.WriteLine(string.IsNullOrEmpty(second));
Console.WriteLine(string.IsNullOrEmpty(third))
两者都返回 true(我预计 string.IsNullOrEmpty(second) 可能会返回 true,但 string.IsNullOrEmpty(third) 会抛出索引越界异常或类似的东西。
我意识到我可以使用match.Groups.Count 的结果来确定示例代码中应该有多少个捕获组 [注意:C# 将 Groups[0] 定义为整个匹配] 但我不想依赖关于这个。
【问题讨论】:
-
为什么不简单地捕获之前和之后的内容,然后从字符串中删除两者,将结果中间“组”作为字符串?
-
我认为您需要一个可选组
@"^\w+\|([^|]+)?\|\w+$",然后通过访问匹配项的.Success属性来检查组是否匹配,请参阅this C# demo。当match2.Groups[1].Success为 false 时,您知道 Group 2 值为空。 -
你需要正则表达式吗?只使用
string.Split是否可行? -
@WiktorStribiżew 谢谢 - 我明白你对可选组的意思。认为您打算执行检查以查看
Success属性是否为真,然后获取值而不是打印布尔值,但我明白了要点。然而,这仍然可以通过首先访问match.Groups.Count以获取组数并以这种方式索引Groups属性来完成,这有点像我想避免的。也许没有超级 clean 方法可以做到这一点。 @JonasH 在此示例代码中是的,但实际代码是一个非常长的管道分隔字符串,其中包含许多(可能是空的)捕获组,所以不太漂亮 -
要知道字符串中是否有捕获组(例如
"abcdef"中没有)然后使用@"^\w+(\|[^|]*\|)?\w+$"和Groups[1].Success将只有True如果有一个捕获组,无论是否为空。