簡體   English   中英

條件.NET正則表達式

[英]Conditional .NET regex

我想寫一個名為F#.NET布爾函數IsStrValid使用決定是否給定的字符串正則表達式s確認以下規則與否:

  • s長4個字符
  • 第1和第3個字符是A,B或C.
  • 第二個字符是1,2或3
  • 第4個字符是1,2或3,除了第1個和第3個字符相同時 - 第4個字符不能與第2個字符相同。

例如:

IsStrValid "A3B3" //true
IsStrValid "A3A3" //false

這是我走了多遠; 卡在條件部分( ??? ):

let IsStrValid (s : string) =   
    Regex.IsMatch(s, @"^([ABC])([123])([ABC])(?(???)[123]|[???])$")

雖然正則表達式支持反向引用 ,但嘗試執行復雜的邏輯,如“如果X然后Y”則相當困難。 您可以使用負前瞻斷言執行類似的操作:

let IsStrValid (s : string) = 
    Regex.IsMatch(s, @"^([ABC][123])(?!\1)[ABC][123]$")

然而,正如Mathew 所說 ,如果它變得比這更復雜,那么直接測試條件可能更容易,如下所示:

let IsStrValid (s : string) =
    let isLet i = Seq.exists ((=)s.[i]) ['A'; 'B'; 'C']
    let isNum i = Seq.exists ((=)s.[i]) ['1'; '2'; '3']
    (s.Length = 4) && (isLet 0) && (isNum 1) && (isLet 2) && (isNum 3) &&
    (s.[0] <> s.[2]) || (s.[1] <> s.[3]) 

這聽起來像條件​​的完美應用,但它們實際上使這項工作更加困難,而不是更少。 以老式的方式做到這一點要容易得多。

^
([ABC])
([123])
(?:
   (?!\1)[ABC][123]
 |
   \1(?!\2)[123]
)
$

這幾乎逐字地實現了您的描述。 如果第三個字符是允許的字母之一,但與第一個字符不同,請抓取它和任何允許的數字。 如果第三個字符與第一個字符相同,則抓住它后跟一個允許的數字,除非它與第一個數字相同。

但我認為即使這比它需要的更復雜。 在我看來,您的要求可以重新設置為與正則表達式[ABC][123]匹配的兩對連續字符,但不能相互匹配

^([ABC])([123])(?!\1\2)[ABC][123]$

我同意Matthew的說法,沒有理由使用正則表達式。 然而,即使沒有反向引用,它當然也是可能的。 首先,有一組有限的字符串,所以你可以把它們全部列出來(或者寫一個簡單的函數來生成這個字符串):

A1A2|A1A3|A1B1|A1B2|...

但是,提出一種略顯荒謬的方法也很容易。 您需要第一個和第三個字符不同,或者第二個和第四個字符不同(或兩個),因此您可以明確地寫出它(使用RegexOptions.IgnorePatternWhitespace ):

[A-C]1[A-C](2|3) |
[A-C]2[A-C](1|3) |
[A-C]3[A-C](2|3) |
A[1-3](B|C)[1-3] |
B[1-3](A|C)[1-3] |
C[1-3](A|B)[1-3]

或者您可以對此進行不同的分組以分解一些重復:

[A-C](1[A-C](2|3)|
      2[A-C](1|3)|
      3[A-C](1|2))|
(A[1-3](B|C)|
 B[1-3](A|C)|
 C[1-3](A|B))[1-3]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM