簡體   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