简体   繁体   English

在命令行程序中将选项与非选项参数分开

[英]Seperating options from non-option arguments in a command-line program

I am trying to write a limited version of ls w/ some options. 我正在尝试写ls w /一些选项的有限版本。

However, I am stuck on the problem of parsing out my options from my arguments in a clean manner. 但是,我一直坚持以一种干净的方式从我的论点中解析我的选择的问题。

For example: 例如:

$ ls -l -t somefile anotherFile

$ ls somefile -lt anotherFile

have the same behavior. 具有相同的行为。

This poses two problems for me: 这给我带来了两个问题:

  1. It makes using argc a bit more difficult. 这使使用argc更加困难。 For example I would consider the arguments ls -lt and ls to both have 0 arguments (other than the name of the command) however argc counts -l as an argument. 例如,我认为参数ls -ltls都具有0个参数(命令名称除外),但是argc将-l视为参数。

Therefore the naive implementation of : 因此,天真的实现:

if( argc == 1) {list all the contents of cwd}

does not work. 不起作用。

Is there a built-in way to get the options as well as the option count, or do I have to roll my own function? 是否有获取选项和选项计数的内置方法,还是我必须滚动自己的函数?

  1. I have to consider all the different ways options can be arranged and be careful not to get an option mixed up as a file name or directory name. 我必须考虑所有不同的方式来排列选项,并且要小心不要混淆选项作为文件名或目录名。 It seems like the cleanest solution is to separate the options from the file arguments from the start. 似乎最干净的解决方案是从一开始就将选项与文件参数分开。 Is there an idiomatic way to do this / is there standard library calls that do this? 是否有惯用的方法来做到这一点?是否有标准的库调用来做到这一点?

There is no built-in argument parsing help, but getopt is the "standard" method for argument parsing. 没有内置的参数解析帮助,但是getopt是用于参数解析的“标准”方法。

For simple apps, I sometimes roll my own with something like: 对于简单的应用程序,有时我会自己添加类似的内容:

int pos=0;
argc--;argv++;
while (argc > 0) {
  if (*argv[0]=='-') {
     switch ((*argv)[1]) {
       case 'l': //-l argument
         save_option_l(++argv);
         argc--; //we consumed one name
         break;
       //... other -options here ...
       default:
         usage("unrecognized option %s", *argv);   
     }
   }
   else {
     save_positional_argument(argv,pos++);
   }
   argv++;
   argc--;
}

In this case, I require the modifiers to directly follow the flags. 在这种情况下,我要求修饰符直接跟随标志。 Don't support variable usage like your first example, unless there are very strong reasons to do so. 不像第一个示例那样支持变量用法,除非有充分的理由这样做。

If you have Gnu's implementation of getopt , it will do all that for you. 如果您有Gnu的getopt实现,它将为您完成所有操作。

Posix standard getopt terminates option processing when it hits the first non-option argument. 当Posix标准getopt遇到第一个非选项参数时,它将终止选项处理。 That conforms to Posix guidelines for utility argument parsing, and many of us prefer this behaviour. 这符合Posix实用程序参数解析的准则,我们中的许多人都喜欢这种行为。 But others like the ability to intermingle options and non-options, and that's the norm for Gnu utilities unless you set an environment variable with the ungainly name POSIXLY_CORRECT . 但是其他功能喜欢混合选项和非选项的功能,这是Gnu实用程序的标准,除非您使用一个笨拙的名称POSIXLY_CORRECT设置环境变量。

Consistent with that preference, Gnu getopt parses arguments: 与该首选项一致,Gnu getopt解析参数:

The default is to permute the contents of argv while scanning it so that eventually all the non-options are at the end. 缺省是在扫描argv时对其内容进行置换,以便最终所有非选项都在末尾。 This allows options to be given in any order, even with programs that were not written to expect this. 这允许以任何顺序给出选项,即使对于未编写程序的程序也是如此。

Note the wording about permuting arguments. 请注意有关置换参数的措辞。 This means that if you start with 这意味着如果您从

ls somefile -lt anotherFile

Gnu getopt will: Gnu getopt将:

  1. Report a l 举报l
  2. Report a t 报告t
  3. Report end of options (-1), leaving optind with the value 2 and argv now looking like: 报告选项(-1)的optind ,现在将optind为2, argv如下所示:

     ls -lt somefile anotherFile 

So now you can process your non-option arguments with: 因此,现在您可以使用以下命令处理非选项参数:

for (int argno = optind; argno < argc; ++argno) {
  /* Do something with argv[argno] */
}

Also, you can tell how many non-option arguments you received with argc-optind , and if argc == optind , you know there weren't any. 另外,您可以使用argc-optind告诉您接收了多少个非选项参数,如果argc == optind ,您知道没有任何参数。

Unbundling -lt into two options is standard Posix getopt behaviour . -lt捆绑为两个选项是标准的Posix getopt behaviour You can combine options lime that as long as the first one doesn't take an argument. 您可以组合选项石灰,只要第一个不带参数即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM