2010-09-27 88 views
3

我不知道如何用常規表達式(或者如果我可以;我是新來的正則表達式)。我有一個角度值的用戶將鍵入,我試圖驗證條目。它的形式是度 - 分 - 秒。我遇到的問題是,如果用戶錯誤地輸入了秒數,我必須找出那個錯誤,但是我的比賽分鐘是成功的。匹配模式[0-9] - [0-9] - [0-9],但沒有匹配[0-9] - [0-9]

或許該方法將更好地解釋:

private Boolean isTextValid(String _angleValue) { 

     Regex _degreeMatchPattern = new Regex("0*[1-9]"); 
     Regex degreeMinMatchPattern = new Regex("(0*[0-9]-{1}0*[0-9]){1}"); 
     Regex degreeMinSecMatchPattern = new Regex("0*[0-9]-{1}0*[0-9]-{1}0*[0-9]"); 

     Match _degreeMatch, _degreeMinMatch, _degreeMinSecMatch; 

     _degreeMinSecMatch = degreeMinSecMatchPattern.Match(_angleValue); 
     if (_degreeMinSecMatch.Success) 
      return true; 

     _degreeMinMatch = degreeMinMatchPattern.Match(_angleValue); 
     if (_degreeMinMatch.Success) 
      return true; 

     _degreeMatch = _degreeMatchPattern.Match(_angleValue); 
     if (_degreeMatch.Success) 
      return true; 

     return false; 
    } 
} 

我要檢查度分鐘,如果度 - 分 - 秒匹配不成功,但前提是用戶沒有輸入任何秒內的數據。我可以通過正則表達式來做到這一點,還是我需要解析字符串並分別評估每個部分?謝謝。

編輯:示例數據將是45-23-10作爲正確的數據。問題是45-23也是有效的數據;理解0秒。因此,如果用戶輸入45-23-1 =意外,我的代碼中的degreeMinMatchPattern正則表達式將成功匹配,即使它是無效的。

第二次編輯:爲了清楚起見,分鐘和第二部分都是可選的。用戶可以輸入45,這是有效的。

+1

你有一些示例數據? – 2010-09-27 17:18:18

+0

它是45-23-1 =。我想你只是沒有看到等號。或許一個更好的例子是45-23-1A。對困惑感到抱歉。 – Shawn 2010-09-27 17:45:13

回答

2

首先,正則表達式中的字符默認匹配一次,所以{1}是多餘的。第二,既然你可以明顯地隔離這個值(你提示只是這個值,而不是在輸入的數據段中尋找它),你應該在你的字符串中包含^和$,以強制字符串應該只包含這種模式。

嘗試「^ \ d {1,3} - \ d {1,2}( - \ d {1,2})?$」。

分解:^匹配字符串的開頭。 \ d匹配任何單個十進制字符,然後在後面指定{1,3},它將匹配任意數字的一到三次出現的集合。那麼你正在尋找一個破折號,然後是一個相似的小數點模式,但只有一兩次。最後一項用括號括起來,以便我們可以對字符進行分組。它的形式與前兩個相似,那麼有一個?將前面的字符組標記爲可選。最後的$表示輸入應該結束。鑑於此,它將匹配222-33-44或222-33,但不匹配222-3344或222-33-abc。

請記住,您可能希望納入其他規則。例如,秒可以表示爲小數(如果您想要小於1秒的分辨率)。您需要選擇期望的小數點和一個或多個附加數字。此外,你可能有一個最大程度的價值;上述正則表達式將匹配最大整數DMS值359-59-59,但它也將匹配999-99-99,這是無效的。你可以使用正則表達式限制最大值(例如「(3 [0-5] \ d | [1-2] \ d {2} | \ d {1,2})」將匹配從0到359的任何數字,通過匹配一個3,然後0-5,然後0-9,或者任何以1或2開頭的3位數字,或者任何兩位數字),但是正如示例所示,正則表達式會變得漫長而混亂,所以在代碼中記錄下你在做什麼。

+0

稍作修改(因爲三者中的第二個也是可選的,並且C#需要第二個反斜槓才能正確地轉義d),所以這種方法很有效。我最後的表述是「^ \\ d {1,3}( - \\ d {1,2}( - \\ d {1,2})?)?$」謝謝! – Shawn 2010-09-27 17:42:54

+0

如果你在打開字符串的雙引號前加@,.NET將自動轉義任何需要它的字符。這對於文件(反斜槓目錄分隔符)和多行數據(\ r \ n無處不在)以及正則表達式非常有用。 – KeithS 2010-09-27 17:49:38

+0

我今天也學到了其他東西(我知道多行數據,但不知道正則表達式)。謝謝! – Shawn 2010-09-27 18:03:33

1

也許你會做得更好,只是解析輸入和檢查是分開。

0

我不知道我理解正確的,但我認爲

(?<degrees>0*[0-9])-?(?<minutes>0*[0-9])(?:-?(?<seconds>0*[0-9]))?$ 

可能會奏效。

但是這很模糊;我也想知道爲什麼你只允許一位數的度/分/秒的值。請顯示您做的一些例子,並且不想匹配。

4

使用{m,}語法,可以指定「模式的這部分必須至少匹配3次」。由於有每個部件之間連字符,分別指定的第一部分,然後將每個連字符數字的組合可以一起之後被分組:

`[0-9](-[0-9]){2,}` 

還可以縮短[0-9]\d\d(-\d){2,}

+0

我認爲他想要匹配2 *或* 3的數字,但只有在沒有任何後續的情況下才可以匹配2個數字,而不是如果一些無效輸入如下。 – 2010-09-27 17:31:17

0

也許你應該嘗試這樣的事情和測試空/無效組:

Regex degrees = new Regex(
       @"(?<degrees>\d+)(?:-(?<minutes>\d+))?(?:-(?<seconds>\d+))?"); 
string[] samples = new []{ "123", "123-456", "123-456-789" }; 
foreach (var sample in samples) 
{ 
    Match m = degrees.Match(sample); 
    if(m.Success) 
    { 
     string degrees = m.Groups["degrees"].Value; 
     string minutes = m.Groups["minutes"].Value; 
     string seconds = m.Groups["seconds"].Value; 
     Console.WriteLine("{0}°{1}'{2}\"", degrees, 
      String.IsNullOrEmpty(minutes) ? "0" : minutes, 
      String.IsNullOrEmpty(seconds) ? "0" : seconds 
     ); 
    } 
} 
相關問題