Multiple regex matches


I have a string that I know will match one (and only one) of three regexes. I want to try each regex in turn until a match is found. For two of the regexes it is sufficient to know that there is a match. The third regex has a capture group and returns an integer.
I have an active pattern for regex:

let (|Regex|_|) pattern input =
let m = Regex.Match(input, pattern)
if m.Success then Some(List.tail [ for g in m.Groups -> g.Value ])
else None

I’m new to F# and struggling for an idiomatic way to do this. I don’t really want to make a convoluted if-then-else expression,
Any help would be really appreciated.


You could create three active patterns that match the three regex patterns you want to match, then just match for them in the order you want. All the if/else will then contained in the active patterns. Having the if/else in the guards may look perfectly fine though, don’t be scared of using if/else theres nothing wrong with using them.

Alternatively you could use FParsec instead of regex.

Example using FParsec:

open FParsec.CharParsers
open FParsec.Primitives

let p1 = skipString "string1" >>. spaces >>. pstring "foo"
let p2 = skipString "string2" >>. spaces >>. pstring "bar"
let p3 = skipString "string3" >>. spaces >>. pstring "baz"

let parser : Parser<string,unit> =
    p1 <|> p2 <|> p3

run parser "string2 bar"

This would successfully parse “bar”

Also, the smaller parsers could have been written using a computated expression which would look like this:

let parser1 = parse {
   do! skipString "string1"
   do! spaces
   let! x = pstring "foo"
   return x }

For your case (if I’m understanding you correctly) you could do something like this:

type MyType
  = Type1
  | Type2
  | Type3 of int

let p1 = skipString "string1" >>. spaces >>. pstring "foo" |>> fun _ -> Type1
let p2 = skipString "string2" >>. spaces >>. pstring "bar" |>> fun _ -> Type2
let p3 = skipString "string3" >>. spaces >>. pint32 |>> Type3

let parser : Parser<MyType,unit> =
  p1 <|> p2 <|> p3

match run parser "string3 1" with
| Success (Type1,_,_)     -> "first parser succeeded"
| Success (Type2,_,_)     -> "second parser succeeded"
| Success ((Type3 i),_,_) -> "third parser succeeded and here's the int: " + string i
| Failure (msg,_,_)       -> msg
1 Like

Hi, I want to ask how to process below strings:
estasdgfb 23435 fsdddgdf
batch size 75
to fetch 75 after batch size?

Currently I will split the whole string and parse line by line with FParsec. I do not know if there is any better way.


I’ll try that thanks.