繁体   English   中英

正则表达式没有给我预期的结果

[英]Regex doesn't give me expected result

好的,我放弃了-是时候请正则表达式专家寻求帮助了。

我正在尝试验证CSV文件的内容,只是看它是否看起来像预期的有效CSV数据。 我并不是要验证所有可能的CSV表单,只是要使它“看起来像” CSV数据,而不是二进制数据,代码文件或其他内容。

每行数据包含逗号分隔的单词,每个单词包含az0-9和少量标点符号,即-_ 文件中可能有几行。 而已。

这是我的简单代码:

const string dataWord = @"[a-z0-9_\-]+";
const string dataLine = "("+dataWord+@"\s*,\s*)*"+dataWord;
const string csvDataFormat = "("+dataLine+") |  (("+dataLine+@"\r\n)*"+dataLine +")";

Regex validCSVDataPattern = new Regex(csvDataFormat, RegexOptions.IgnoreCase);
protected override bool IsCorrectDataFormat(string fileContents)
{
    return validCSVDataPattern.IsMatch(fileContents);
}

这给了我一个正则表达式模式

(([a-z0-9_\-]+\s*,\s*)*[a-z0-9_\-]+) |  ((([a-z0-9_\-]+\s*,\s*)*[a-z0-9_\-]+\r\n)*([a-z0-9_\-]+\s*,\s*)*[a-z0-9_\-]+)

但是,如果我用一段C#代码来呈现它,则正则表达式解析器会说这是匹配项。 那个怎么样? C#代码看起来不像我的CSV模式(开始时,除了_-以外,还有标点符号)。

谁能指出我明显的错误? 让我重复一遍-我并不是要验证所有可能的CSV表单,而只是验证我的简单子集。

您的正则表达式缺少^ (行的开头)和$ (行的结尾)锚。 这意味着它将与包含该表达式描述的内容的任何文本匹配,即使该文本包含其他完全不相关的部分。

例如,此文本与表达式匹配:

foo, bar

因此,此文本还与以下内容匹配:

var result = calculate(foo, bar);

您可以看到前进的方向。

csvDataFormat的开头添加^ ,在结尾添加$ ,以获取所需的行为。

这是一种更好的模式,用于在每行中一对多查找CSV组(例如XXX,yyy

^([\w\s_\-]*,?)+$

^ -每行的开头

( -CSV匹配组开始

[\\w\\s_\\-]* -每个CSV中的有效字符\\w (a-zA-Z0-9)以及_-

,? -可能是逗号

)+ -csv匹配组的末尾,其中有1个是预期的。

这将验证整个文件,一行行的基本CSV结构,并允许空,,情况。

我想出了这个正则表达式:

^([a-z0-9_\-]+)(\s*)(,\s*[a-z0-9_\-]+)*$

测试

asbc_- ,   khkhkjh,    lkjlkjlkj_-,     j : PASS
asbc,                                     : FAIL
asbc_-,khkhkjh,lkjlkjlk909j_-,j           : PASS

如果你想匹配空行一样,,,或者当某些值是空白样,abcd,,使用

^([a-z0-9_\-]*)(\s*)(,\s*[a-z0-9_\-]*)*$

循环浏览所有行以查看文件是否正常:

const string dataLine = "^([a-z0-9_\-]+)(\s*)(,\s*[a-z0-9_\-]+)*$";
Regex validCSVDataPattern = new Regex(csvDataFormat, RegexOptions.IgnoreCase);
protected override bool IsCorrectDataFormat(string fileContents)
{
    string[] lines = fileContents.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);

    foreach (var line in lines)
    {
        if (!validCSVDataPattern.IsMatch(line))
        return false;
    }

    return true;
}

我认为这是您要寻找的:

@"(?in)^[a-z0-9_-]+( *, *[a-z0-9_-]+)*([\r\n]+[a-z0-9_-]+( *, *[a-z0-9_-]+)*)*$"

值得注意的变化是:

  • 添加了锚( ^$ ,因为没有它们的正则表达式是毫无意义的
  • 删除的空格(必须与文字空格匹配,我认为这不是您想要的)
  • 取代了\\s在每次出现\\s*与文字空间(因为\\s可以匹配任何空白字符,而您只希望匹配这些点实际的空间)

在此之前,您的正则表达式的基本结构看起来还不错| 来了,把事情搞砸了。 ;)

ps,以防万一, (?in)是一个内联修饰符,用于设置IgnoreCaseExplicitCapture模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM