首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有多个值的应用程序选项

具有多个值的应用程序选项
EN

Stack Overflow用户
提问于 2016-01-20 00:35:37
回答 1查看 2.1K关注 0票数 12

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

代码语言:javascript
复制
$ ./program -a file1 file2 -b filea fileb

也就是说,两个开关,两者都可以采用多个参数。

因此,我为我的选项提供了一个数据类型,如下所示:

代码语言:javascript
复制
data MyOptions = MyOptions {
    aFiles :: [String]
  , bFiles :: [String] }

然后像这样的Parser

代码语言:javascript
复制
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

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

我想知道我是否可以假装我想要四个选项:一个布尔开关(即-a);一个字符串列表;另一个布尔开关(即-b);另一个字符串列表。所以我改变了我的数据类型:

代码语言:javascript
复制
data MyOptions = MyOptions {
    isA    :: Bool
  , aFiles :: [String]
  , isB    :: Bool
  , bFiles :: [String] }

然后对解析器进行如下修改:

代码语言:javascript
复制
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开关后面的参数。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-20 07:34:18

除了命令之外,optparse-applicative遵循getopts约定:命令行上的单个参数对应于单个选项参数。它甚至更严格一点,因为getopts将允许具有相同开关的多个选项:

代码语言:javascript
复制
./program-with-getopts -i input1 -i input2 -i input3

所以没有“魔法”可以帮助你立即使用你的程序

代码语言:javascript
复制
./program-with-magic -a 1 2 3 -b foo bar crux

因为编写Options.Applicative.Parser时没有考虑到这一点;它也与POSIX公约相矛盾,在这种情况下,选项可以是一个参数,也可以是零参数。

但是,您可以从两个方面解决这个问题:或者像在-a中那样多次使用getopts,或者告诉用户使用引号:

代码语言:javascript
复制
./program-as-above -a "1 2 3" -b "foo bar crux" 
# works already with your program!

要启用一个选项的多次使用,您必须使用many (如果它们是可选的)或some (如果不是)。您甚至可以组合这两种变体:

代码语言:javascript
复制
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")

它使您能够使用

代码语言:javascript
复制
./program-with-posix-style -a 1 -a "2 3" -b foo -b "foo bar"

但是我所知道的任何解析库都不支持您建议的样式,因为自由参数的位置可能是不明确的。如果您真的想使用-a 1 2 3 -b foo bar crux,您必须自己解析参数。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34889516

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档