2010-12-27 4 views
1
  let IntAndString value = 
       let (|Match|_|) pattern input = 
        let m = Regex.Match(input, pattern) in 
        if m.Success then Some ([ for g in m.Groups -> g.Value ]) else None 
       match value with 
        | Match "(\d+)(\w+)" x -> Some(x) 
        //| Match "(\w+)" x  -> Some(x) 
        | Match "(\d+)" x  -> Some(x @ ["items"]) 
        | _      -> None  

だから私は正規表現マッチは別々のない値とテキスト

10a -> 10 , a it works 
100a -> 100 , a doesn't works - no idea why 
100 -> 100 , items doesn't works 

なぜ100aを望むことができます - > 100を、aがない作品とどのように私はそれを実現できるのでしょうか?

+0

何をキャッチしますか? – ykatchou

答えて

2

あなたの質問が正しく分かっていれば、文字列に数字だけが含まれている場合は2番目の一致句が使用されます。数字が続く場合は最初の一致句が使用されます。

問題は\wクラスはapparentelyも(あなたが単純なパターンを使用して、それを試すことができます)の数字が含まれていることですので、あなたが\d\wに対して10と一致したときにエンジンが\dから1\wから0を割り当てます。あなたが遭遇した動作を説明する必要がありregular expressionsため

let IntAndString value = 
    match value with 
    | Match "([0-9]+)([^0-9]+)" x -> Some(x) 
    | Match "([0-9]+)" x   -> Some(x @ ["items"]) 
    | _       -> None  

IntAndString "100" 

ドキュメント:

あなたはこのような単純なものを試すことができます。

+0

数量子は '?'を付けないと貪欲ですので、 '\ d +'はすべての文字を最初の非数字にキャッチし、後に '\ w 'はすべての文字と数字をキャッチします。正規表現に '^'と '$'があるべきか、 '\ w'が' .'でなければならないのだろうかと思います。 – YotaXP

+1

@ YotaXP - そうではありません。 '\ d +'はできるだけ長い部分文字列を最初にマッチさせようとしますが、それでもバックトラックします。したがって、 '\ d + \ w +'と '' 100 "'をマッチさせると、 '\ d +'は文字列全体を取得しようとします。しかし、 '\ w +'の文字が残っていなければ、 '\ d +'を '' 10 "'にマッチさせ、 '\ w +'に '' 0 "'を残してバックトラックを開始します。真の貪欲な(バックトラックしない)マッチでは、 '((?> \ d +))(\ w +)'を使うことができます。 – kvb

+1

あなたの解決策は、数字クラスに他の文化の桁も示すUnicode文字が含まれているという点で、オリジナルとは異なる動作をしていることに注意してください(アラビア語 - インド数字0 'など)。オリジナルと一致させるために、 '@ '(\ d +)([^ \ d] +)' 'が良いでしょう。 – kvb

0

と同じように試してください。 "(\ d +)(\ w *)" と一致すると、+が1回以上発生します。 *は0回以上を意味します。

関連する問題