寻求支持嵌套命令行参数解析的F#现成库解决方案
Argu本身就支持你需要的按任务类型解析对应参数的需求,你之前应该是没用到它的**子命令(Subcommand)**功能,这个功能就是基于可区分联合实现的,完全匹配你的使用场景,不用额外找其他解决方案。
实现步骤
1. 定义参数结构
我们需要同时兼容你提到的两种调用格式,参数定义如下:
open Argu // 定义magic任务对应的参数 [<CliPrefix(CliPrefix.Dash)>] type MagicArgs = | [<AltCommandLine("-param1")>] Param1 of string | [<AltCommandLine("-param2")>] Param2 of string interface IArgParserTemplate with member s.Usage = match s with | Param1 _ -> "magic任务的param1参数" | Param2 _ -> "magic任务的param2参数" // 定义no-magic任务对应的参数 [<CliPrefix(CliPrefix.Dash)>] type NoMagicArgs = | [<AltCommandLine("-param3")>] Param3 of string | [<AltCommandLine("-param4")>] Param4 of string interface IArgParserTemplate with member s.Usage = match s with | Param3 _ -> "no-magic任务的param3参数" | Param4 _ -> "no-magic任务的param4参数" // 总命令参数,同时支持直接子命令和-task参数两种格式 type CliArguments = | [<AltCommandLine("-task")>] Task of taskName:string * [<Rest>] args:string list | [<Subcommand>] Magic of ParseResults<MagicArgs> | [<Subcommand>] NoMagic of ParseResults<NoMagicArgs> interface IArgParserTemplate with member s.Usage = match s with | Task _ -> "指定执行的任务类型,后跟任务对应参数" | Magic _ -> "执行magic任务,后跟对应参数" | NoMagic _ -> "执行no-magic任务,后跟对应参数"
2. 实现解析逻辑,映射到你的配置类型
type MagicOptions = { Param1: string Param2: string } type NoMagicOptions = { Param3: string Param4: string } let tryParseCommandLine argv = let parser = ArgumentParser.Create<CliArguments>(programName = "app.exe") let parseResult = parser.Parse(argv) match parseResult.GetAllResults() |> List.head with // 处理直接子命令的调用格式:app.exe magic -param1 xxx -param2 xxx | Magic magicArgs -> Ok { Param1 = magicArgs.GetResult(Param1) Param2 = magicArgs.GetResult(Param2) } :> obj |> Ok | NoMagic noMagicArgs -> Ok { Param3 = noMagicArgs.GetResult(Param3) Param4 = noMagicArgs.GetResult(Param4) } :> obj |> Ok // 处理带-task参数的调用格式:app.exe -task magic -param1 xxx -param2 xxx | Task (taskName, restArgs) -> match taskName.ToLowerInvariant() with | "magic" -> let magicParser = ArgumentParser.Create<MagicArgs>() let magicRes = magicParser.Parse(restArgs) Ok { Param1 = magicRes.GetResult(Param1) Param2 = magicRes.GetResult(Param2) } :> obj |> Ok | "no-magic" -> let noMagicParser = ArgumentParser.Create<NoMagicArgs>() let noMagicRes = noMagicParser.Parse(restArgs) Ok { Param3 = noMagicRes.GetResult(Param3) Param4 = noMagicRes.GetResult(Param4) } :> obj |> Ok | invalidTask -> Error $"不支持的任务类型:{invalidTask}" | _ -> Error "请指定要执行的任务类型"
其他说明
- 如果你不需要兼容
-task的调用格式,直接用原生子命令即可,不需要单独处理Task分支,代码会更简洁 - Argu的子命令解析会自动校验参数,只会解析当前任务对应的参数,不符合的参数会直接抛出错误提示,完全符合你的需求
- 如果你的场景非常轻量,不想引入Argu,也可以自己手动实现解析逻辑:先读取第一个参数或者
-task的值确定任务类型,再按对应的参数名匹配后续值即可
内容的提问来源于stack exchange,提问作者dr11
相关产品推荐
相关产品推荐

