我需要验证可以使用两种格式之一的值,并尝试使用单个正则表达式,但无法弄清楚它为什么不起作用。
第一种格式恰好是17个字母数字字符,表达式^[A-Za-z0-9]{17}$
正确匹配测试值5UXWX7C56BA123456
,但没有缩短的值5UXWX7C56BA12345
或加长的值5UXWX7C56BA1234569
。< / p>
第二种格式恰好是8个字母数字字符,后跟星号或下划线,另外还有两个字母数字字符。表达式^[A-Za-z0-9]{8}[*_][A-Za-z0-9]{2}$
正确匹配测试值5UXWX7C5*BA
,但不是缩短的值5UXWX7C5*B
或加长的值5UXWX7C5*BA1
。
然而,当我尝试组合表达式时,我会得到不同的意外结果,具体取决于我首先放置的子表达式。以下代码片段演示了
var pattern1 = new Regex(@"^([A-Za-z0-9]{17})|([A-Za-z0-9]{8}[*_][A-Za-z0-9]{2})$");
var pattern2 = new Regex(@"^([A-Za-z0-9]{8}[*_][A-Za-z0-9]{2})|([A-Za-z0-9]{17})$");
var values = new string[]
{
"5UXWX7C56BA12345", "5UXWX7C56BA123456", "5UXWX7C56BA1234569",
"5UXWX7C5*B", "5UXWX7C5*BA", "5UXWX7C5*BA1"
};
Console.WriteLine($"Using {pattern1}\n");
Console.WriteLine($" {"Value",-20}{"IsMatch",-9}{"Expected",-10}");
Console.WriteLine($" {new string('-', 37)}");
values
.Select(x => new { Value = x, Result = pattern1.IsMatch(x), ExpectedResult = x.Length == 11 || x.Length == 17 })
.Select(x => $" {x.Value,-20}{x.Result,-9}{x.ExpectedResult} {(x.Result == x.ExpectedResult ? "" : "UNEXPECTED")}")
.WithEach(Console.WriteLine);
Console.WriteLine($"\n\nUsing {pattern2}\n");
Console.WriteLine($" {"Value",-20}{"IsMatch",-9}{"Expected",-10}");
Console.WriteLine($" {new string('-', 37)}");
values
.Select(x => new { Value = x, Result = pattern2.IsMatch(x), ExpectedResult = x.Length == 11 || x.Length == 17 })
.Select(x => $" {x.Value,-20}{x.Result,-9}{x.ExpectedResult} {(x.Result == x.ExpectedResult ? "" : "UNEXPECTED")}")
.WithEach(Console.WriteLine);
产生以下结果
Using ^([A-Za-z0-9]{17})|([A-Za-z0-9]{8}[*_][A-Za-z0-9]{2})$
Value IsMatch Expected
-------------------------------------
5UXWX7C56BA12345 False False
5UXWX7C56BA123456 True True
5UXWX7C56BA1234569 True False UNEXPECTED
5UXWX7C5*B False False
5UXWX7C5*BA True True
5UXWX7C5*BA1 False False
Using ^([A-Za-z0-9]{8}[*_][A-Za-z0-9]{2})|([A-Za-z0-9]{17})$
Value IsMatch Expected
-------------------------------------
5UXWX7C56BA12345 False False
5UXWX7C56BA123456 True True
5UXWX7C56BA1234569 True False UNEXPECTED
5UXWX7C5*B False False
5UXWX7C5*BA True True
5UXWX7C5*BA1 True False UNEXPECTED
我希望有人能够在我的表达中指出错误。似乎虽然我正在使用^和$来尝试强制匹配整个行/值,但是当某个匹配被发现更长时,即使存在进一步不匹配的字符,我本来希望它会导致整个值不是匹配。
虽然我使用LINQPad运行上面的代码片段,但我看到了来自regex101.com的相同结果。
答案 0 :(得分:3)
您的正则表达式未正确锚定:
^([A-Za-z0-9]{17})|([A-Za-z0-9]{8}[*_][A-Za-z0-9]{2})$
^ ^ ^ ^
这里,([A-Za-z0-9]{17})
仅锚定在字符串的开头(并且在该模式之后可以有任何内容)并且([A-Za-z0-9]{8}[*_][A-Za-z0-9]{2})
仅锚定在字符串的末尾(并且可以有任何内容)在那种模式之前)。
同样的问题是第二种模式,你只是换了替代品。
使用
var pattern1 = new Regex(@"^(?:[A-Za-z0-9]{17}|[A-Za-z0-9]{8}[*_][A-Za-z0-9]{2})$");
^ ^ ^
否则,您的替代方案不会停留在两个方面。
请参阅regex demo。