C# 与正则表达式存在错误匹配,don';我不知道如何修理

C# 与正则表达式存在错误匹配,don';我不知道如何修理,c#,regex,C#,Regex,我正在尝试检测模式: 字符串“BP”后跟2或4个双精度值(我稍后将捕获这些值),所有值都由空格分隔 例如: BP 1.0 3.5 BP-1e-3 0.72 3.7 1.22e2 为了检测double,我使用了我从中获得的模式[+\-]?(?:0[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+) 不幸的是,在测试了几个字符串之后,我发现我的代码无法区分字符串BP后面是2或4个数字。下面是一些测试用例: void Main() { var testString =

我正在尝试检测模式:

字符串“BP”后跟2或4个双精度值(我稍后将捕获这些值),所有值都由空格分隔

例如:

  • BP 1.0 3.5
  • BP-1e-3 0.72 3.7 1.22e2
为了检测double,我使用了我从中获得的模式
[+\-]?(?:0[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)

不幸的是,在测试了几个字符串之后,我发现我的代码无法区分字符串
BP
后面是2或4个数字。下面是一些测试用例:

void Main()
{
    var testString = "BP -1.23e4 5.67";

    var mspaces = @"\s*"; // meaning as many spaces as you want
    var cdouble = @"([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)"; // meaning capture a double

    var shortPattern = String.Join("",  mspaces, "BP", mspaces, cdouble, mspaces, cdouble, mspaces);
    var longPattern = String.Join("",  mspaces, "BP", mspaces, cdouble, mspaces, cdouble, mspaces, cdouble, mspaces, cdouble, mspaces);

    var bpShort = Regex.Match(testString, shortPattern, RegexOptions.IgnoreCase);
    var bpLong = Regex.Match(testString, longPattern, RegexOptions.IgnoreCase);

    if (bpLong.Success)
    {
        Console.WriteLine("Long pattern detected"); // !!FALSE-MATCH!!
    }
    if (bpShort.Success)
    {
        Console.WriteLine("Short pattern detected");
    }   
}  
在本例中,即使只有两个数字(
-1.23e4
5.67
),代码也会匹配4个不同的数字(
-1.23e4
5.
6
7


也许我添加了圆括号来表示我想要捕获所有数字子元素是错误的,或者我应该进一步表示一个带有空格或字符串结尾的双端点,我不知道?

这很明显。正则表达式总是希望找到尽可能多的匹配项。因此,如果您查找四个数字,正则表达式将尽最大努力分割字符串,以便匹配四个数字

要解决此问题,需要在两个匹配项之间强制使用空格

这可以通过更换以下部件来实现:

var mspaces = @"\s*";
作者:

+
表示一个或多个,而
*
表示零或多个,因此正则表达式可以决定不在两个数字之间使用空格。)

您还应该删除正则表达式连接中的起始空格。从而取代:

String.Join("",  mspaces, "BP"...
作者:

以及尾随
mspace
。在这种情况下,一个得到

也许您不想匹配像
abp15
这样的字符串,因为
A
BP
之间必须有一些空格。在这种情况下,您可以使用
@“\b”


最后,正如@MattBurland所说,任何有四个数字的模式当然是有两个数字的模式。如果希望字符串以结尾,可以在结尾使用
$
。如果希望字符串以
BP
开头,可以在前面使用
^

看起来像是非贪婪匹配。作为旁注,如果你的分隔符是空的,你可以使用<代码>字符串.CONTAG< /COD>而不是<代码>连接< /代码>。为什么不与 Couth模式匹配,看看是否有2个或4个匹配项?对于OP也是值得注意的,长字符串也将与短模式匹配,它们可能会被认为是一个错误。添加锚定(
^
$
)可以解决这个问题。非常感谢您提供这些清晰的解释,这很有意义。使用
$
也比先测试长字符串再测试短字符串要好得多(这就是我想要区分两者的方式)。对于信息,我正在解析的字符串是从文件中读取的过滤器描述。我有类似
BP1.0 2.0
(带通介于1.0和20之间)或
BR 1.0 1.1 2.0 2.1
(带阻,第一次转换为1.0到1.1,第二次转换为2.0到2.1)。有时在
BP
BR
HP
字母之前有额外的空格…修剪就足够了。。
String.Join("",  mspaces, "BP"...
String.Join("",  "BP"...