oct*_*bus 2 f# command-line parsing pattern-matching
我允许像这样的命令行参数--10GB
,其中--
和GB
是常量,但是可以在常量值之间替换像 1、10 或 100 这样的数字,例如--5GB
。
我可以轻松解析字符串的开头和结尾substr
,但想使用match
它。我只是不确定如何构造匹配表达式。
let GB1 = cvt_bytes_to_gb(int64(DiskFreeLevels.GB1))
let arg = argv.[0]
let match_head = "--"
let match_tail = "GB"
let parse_min_gb_arg arg =
match arg with
| match_head & match_tail -> cvt_gb_arg_to_int arg
| _ -> volLib.GB1
Run Code Online (Sandbox Code Playgroud)
我收到一条警告,提示_ This rule will never be matched.
“如何构建 AND 表达式?”
除了匹配整个值之外,您不能匹配字符串,例如match s with | "1" -> 1 | "2" -> 2 ...
解析开头和结尾将是最有效的方法,无需变得聪明(顺便说一句,这是一个普遍正确的陈述)。
但如果你真的想使用模式匹配,那绝对是可以做到的,但是您必须为自己制作一些自定义匹配器(也称为“活动模式”)。
首先,创建一个自定义匹配器,它将解析出由前缀和后缀包围的字符串的“中间”部分:
let (|StrBetween|_|) starts ends (str: string) =
if str.StartsWith starts && str.EndsWith ends then
Some (str.Substring(starts.Length, str.Length - ends.Length - starts.Length))
else
None
Run Code Online (Sandbox Code Playgroud)
用法:
let x = match "abcd" with
| StrBetween "a" "d" s -> s
| _ -> "nope"
// x = "bc"
Run Code Online (Sandbox Code Playgroud)
然后创建一个自定义匹配器来解析一个整数:
let (|Int|_|) (s: string) =
match System.Int32.TryParse s with
| true, i -> Some i
| _ -> None
Run Code Online (Sandbox Code Playgroud)
用法:
let x = match "15" with
| Int i -> i
| _ -> 0
// x = 15
Run Code Online (Sandbox Code Playgroud)
现在,将两者结合起来:
let x = match "--10GB" with
| StrBetween "--" "GB" (Int i) -> i
| _ -> volLib.GB1
// x = 10
Run Code Online (Sandbox Code Playgroud)
模式的这种组合和嵌套的能力是它们的主要功能:您可以用易于理解的小片段构建复杂的模式,并让编译器将其与输入相匹配。这基本上就是为什么它被称为“模式匹配”。:-)