正则表达式没有给我预期的结果
本文关键字:结果 正则表达式 | 更新日期: 2023-09-27 18:19:00
好吧,我放弃了 - 是时候向正则表达式大师寻求帮助了。
我正在尝试验证 CSV 文件内容,只是为了看看它是否看起来像预期的有效 CSV 数据。我并没有试图验证所有可能的CSV表单,只是它"看起来像"CSV数据,而不是二进制数据,代码文件或其他任何东西。
每行数据由逗号分隔的单词组成,每个单词包含a-z
、0-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
可以匹配任何空格字符,而您只想匹配这些位置的实际空格(
正则表达式的基本结构看起来相当不错,直到|
出现并把事情搞砸了。 ;)
p.s.,如果您想知道,(?in)
是一个内联修饰符,用于设置IgnoreCase
和ExplicitCapture
模式。