我正在尝试在F#中编写一个匹配像
这样的东西的正则表达式.float -.05, 2.4
.float 31.1234
.float -0.5, 1.0, 1.1
我正在尝试这样的事情
let matchFloat input =
let matches = Regex(@"(\.float )?(?<float>[+-]?\d*\.\d+)").Matches(input)
([for m in matches -> m.Groups.["float"].Value, matches.Count > 0)
哪种作品,但我对.double有同样的事情,无论我的匹配表达式中的第一个是匹配的那个 - 因为我做了“发生0或1次”,这意味着任何一个指令后面的浮点数字符串都将被视为相同。
那么如何在不进行输入的情况下确保.float存在.StartsWith(...)?我知道我可以编写这个正则表达式,以便它能够正确匹配,并且m.Groups。[“float”]。值将仅返回我需要的内容,而不会在事后删除空格或逗号。
我一直在搞乱这件事几个小时,只是不能让它做我想做的事。我尝试过使用lookbehind / lookahead的东西,以及其他一些东西,但没有运气。
请帮忙! :)
答案 0 :(得分:4)
嗯,这可以帮助您顺利前往step 1 of fixing a Linux machine
您可以使用正向lookbehind与替换相结合来捕获行开头的.float
或.decimal
到一个组,然后检查捕获了哪一个。 lookbehind本身不会对主要捕获做出贡献,因此数字仍然是&#34; group 0&#34;中的唯一内容。
然后我最喜欢的一点点 - 通过在lookbehind中添加.*
(float
或decimal
之后),你可以成功地从输入字符串返回多个匹配,每个匹配共享初始.float
或.decimal
,但随后每次缩放以捕获不同的数字集。
用一点DU型设一个弓来代表两种情况:
type DataPoint =
| Float of string
| Decimal of string
let parse input =
let patt = "(?<=^\.((float)|(decimal)).*(,?\s+))[+-]?\d*\.\d+(?=\s*(,|$))"
Regex.Matches(input, patt)
|> Seq.cast<Match>
|> Seq.map (fun m ->
match (m.Groups.[2].Success, m.Groups.[3].Success) with
| (true, false) -> Float(m.Value)
| (false, true) -> Decimal(m.Value)
| _ -> failwith "??")
|> List.ofSeq
// positive cases
parse ".float -.05, 2.4" // [Float "-.05"; Float "2.4"]
parse ".float 31.1234" // [Float "31.1234"]
parse ".float -0.5, 1.0, 1.1" // [Float "-0.5"; Float "1.0"; Float "1.1"]
parse ".decimal 123.456, -22.0" // [Decimal "123.456"; Decimal "-22.0"]
// negative cases, plucks out valid bits
parse ".decimal xyz,,.., +1.0, .2.3.4, -.2 " // [Decimal "+1.0"; Decimal "-.2"]
parse ".float 1.0, 2.0-, 3." // [Float "1.0"]
请注意,我只是依赖于群组编号,您可能需要更加小心并使用命名群组。
另外值得注意的是,.NET是one of the only regex environments,支持在lookbehind中完全交替和.*
匹配,所以这可能不是可移植的。
编辑:我根据反馈在某种程度上加强了对负输入的模式。仍然没有防弹。
答案 1 :(得分:1)
实际上我没有看到任何理由在这种情况下Regex是有用的。使用字符串函数和系统解析函数是更可读和类型安全的解析输入的方法。借用@ latkin的答案借用DataPoint:
open System
type DataPoint =
| Float of float
| Decimal of decimal
let listparse parser mapper =
List.choose (fun f -> match parser f with true, v -> Some (mapper v) | _ -> None)
let parse (input: string) =
match Array.toList (input.Split([|',';' '|])) with
| ".float"::rest -> rest |> listparse Double.TryParse Float
| ".decimal"::rest -> rest |> listparse Decimal.TryParse Decimal
| _ -> []
使用.TryParse()方法中的额外参数,您可以轻松处理更复杂的浮点输入格式,如指数表示法(例如1.3E5)
答案 2 :(得分:-1)
试试这个\.float [+-]?[0-9\., ]+
并提及此(http://regex101.com/r/kW6zZ1/1)