gpt4 book ai didi

haskell - 具有多个值的 optparse-applicative 选项

转载 作者:行者123 更新时间:2023-12-04 12:06:00 26 4
gpt4 key购买 nike

我正在使用 optparse-applicative我希望能够解析命令行参数,例如:

$ ./program -a file1 file2 -b filea fileb

即两个开关,它们都可以接受多个参数。

所以我的选项有一个数据类型,如下所示:
data MyOptions = MyOptions {
aFiles :: [String]
, bFiles :: [String] }

然后是 Parser像这样:
config :: Parser MyOptions
config = MyOptions
<$> option (str >>= parseStringList)
( short 'a' <> long "aFiles" )
<*> option (str >>= parseStringList)
( short 'b' <> long "bFiles" )

parseStringList :: Monad m => String -> m [String]
parseStringList = return . words

这种方法失败的原因是,当每个开关只提供一个参数时,它会给出预期的结果,但是如果你提供第二个参数,你会得到第二个参数的“无效参数”。

我想知道我是否可以通过假装我想要四个选项来组合它:一个 bool 开关(即 -a );字符串列表;另一个 bool 开关(即 -b );和另一个字符串列表。所以我改变了我的数据类型:
data MyOptions = MyOptions {
isA :: Bool
, aFiles :: [String]
, isB :: Bool
, bFiles :: [String] }

然后像这样修改解析器:
config :: Parser MyOptions
config = MyOptions
<$> switch
( short 'a' <> long "aFiles" )
<*> many (argument str (metavar "FILE"))
<*> switch
( short 'b' <> long "bFiles" )
<*> many (argument str (metavar "FILE"))

这次使用 manyargument组合器而不是字符串列表的显式解析器。

但是现在第一个 many (argument str (metavar "FILE"))使用所有参数,包括 -b 之后的参数转变。

那么我该如何编写这个参数解析器呢?

最佳答案

除了命令,optparse-applicative关注 getopts 约定:命令行上的单个参数对应于单个选项参数。它甚至更严格一些,因为 getopts将允许使用相同开关的多个选项:

./program-with-getopts -i input1 -i input2 -i input3

所以没有“魔法”可以帮助你立即使用你的程序,比如
./program-with-magic -a 1 2 3 -b foo bar crux

自从 Options.Applicative.Parser没有考虑到这一点;它也与 POSIX conventions 相矛盾。 , 其中 options 接受一个参数或不接受。

但是,您可以从两个方面解决这个问题:要么使用 -a几次,就像您在 getopts 中所做的那样,或告诉用户使用引号:
./program-as-above -a "1 2 3" -b "foo bar crux" 
# works already with your program!

要启用一个选项的多次使用,您必须使用 many (如果它们是可选的)或 some (如果不是)。您甚至可以结合两种变体:
multiString desc = concat <$> some single
where single = option (str >>= parseStringList) desc

config :: Parser MyOptions
config = MyOptions
<$> multiString (short 'a' <> long "aFiles" <> help "Use quotes/multiple")
<*> multiString (short 'b' <> long "bFiles" <> help "Use quotes/multiple")

这使您能够使用
./program-with-posix-style -a 1 -a "2 3" -b foo -b "foo bar"

但是我知道的任何解析库都不支持您提出的样式,因为自由参数的位置会模棱两可。如果你真的想用 -a 1 2 3 -b foo bar crux ,您必须自己解析参数。

关于haskell - 具有多个值的 optparse-applicative 选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34889516/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com