我允许使用像--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
我收到警告说_ This rule will never be matched.
如何构建AND表达式是什么?
答案 0 :(得分:4)
我能想到的最好的是使用部分活动模式:
let (|GbFormat|_|) (x:string) =
let prefix = "--"
let suffix = "GB"
if x.StartsWith(prefix) && x.EndsWith(suffix) then
let len = x.Length - prefix.Length - suffix.Length
Some(x.Substring(prefix.Length, len))
else
None
let parse_min_gb_arg arg =
match arg with
| GbFormat gb -> gb
| _ -> volLib.GB1
parse_min_gb_arg "--42GB"
答案 1 :(得分:4)
您不能匹配字符串,除了匹配整个值,例如match s with | "1" -> 1 | "2" -> 2 ...
解析开始和结束将是最有效的方法,没有必要变得聪明(顺便说一下,这是一个普遍真实的陈述)。
但如果确实想要使用模式匹配,那么肯定可以这样做,但是你必须自己制作一些自定义匹配器(也称为"活动模式& #34;。)
首先,制作一个自定义匹配器来解析"中间"由前缀和后缀包围的字符串的一部分:
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
用法:
let x = match "abcd" with
| StrBetween "a" "d" s -> s
| _ -> "nope"
// x = "bc"
然后创建一个解析整数的自定义匹配器:
let (|Int|_|) (s: string) =
match System.Int32.TryParse s with
| true, i -> Some i
| _ -> None
用法:
let x = match "15" with
| Int i -> i
| _ -> 0
// x = 15
现在,结合两者:
let x = match "--10GB" with
| StrBetween "--" "GB" (Int i) -> i
| _ -> volLib.GB1
// x = 10
这种组合和嵌套模式的能力是它们的主要力量:你可以用小的,易于理解的部分构建一个复杂的模式,并让编译器将它与输入匹配。这基本上就是为什么它被称为" 模式匹配"。 : - )