Looking at Chapter 21, I introduced the magic tool getopt to parse the command line, and learned how to handle the general command line under linux.
The command line can be divided into parameters and options. The ones without - or - prefix are parameters. For a command, the number is fixed, and the order of multiple parameters is fixed (otherwise, the command cannot distinguish); the options are with - or-- The prefixes can be optional or not, which is determined by the user's input. In addition, the options can also have their own follow parameters, and there is no order between them. for instance:
> wget -c http://strawberryperl.com/download/5.30.2.1/strawberry-perl-5.30.2.1-32bit.msi
The wget command line has two inputs, one is the option - c, which indicates the breakpoint renewal; the other is the parameter url, which is the download address in the following list.
Of course, this is just a simple example. There are no multiple parameters, options or parameters. Later, we will make a complex example to verify.
Back to getopt, its purpose is to simplify the processing of these inputs.
How to simplify it is to define an acceptable option "template" and then parse all options by calling getopt constantly,
The last remaining parameters are unrecognizable, but this scenario is simple, just deal with them in order.
Here is an example for verification:
1 #include "../apue.h" 2 int main (int argc, char *argv[]) 3 { 4 int c, i; 5 char fmt[1024] = { 0 }; 6 char *abc = "abcdefghijklmnopqrtsuvwxyz"; 7 char *ABC = "A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:V:W:X:Y:Z:"; 8 strcat (fmt, abc); 9 strcat (fmt, ABC); 10 while ((c = getopt (argc, argv, fmt)) != -1) { 11 printf ("got option [%d]: '%c' ('%c')", optind, c, optopt); 12 if (optarg) 13 printf (" arg: '%s'", optarg); 14 15 printf ("\n"); 16 } 17 18 printf ("end up at %d\n", optind); 19 if (optind < argc) 20 printf ("some argument left, from %s\n", argv[optind]); 21 exit (1); 22 }
This example is more "greedy". It defines all the letters as options. The lower case letters do not have parameters, and the upper case letters have parameters. Finally, print the parameters that cannot be parsed.
It can be used to verify whether getopt is executed correctly:
$ ./getopt -a -b -c -A 1 -B 2 -C 3 admin 123qwe got option [2]: 'a' ('') got option [3]: 'b' ('') got option [4]: 'c' ('') got option [6]: 'A' ('') arg: '1' got option [8]: 'B' ('') arg: '2' got option [10]: 'C' ('') arg: '3' end up at 10 some argument left, from admin
The return values of some getopt related facilities (optind / optarg / optop) are printed so that you can see how they change as the options are parsed.
In the brackets are the values represented by optind, indicating the location of the next input in argv.
When all options are resolved, the location is updated to the end or first parameter location, if any.
I always have a question, if the parameter is included in the option, where is the location?
If you navigate to the location of that parameter, will the application traverse to the parsed option when traversing the remaining parameters backward?
If not, isn't a parameter missing?
So I did a test with this small program, like this:
$ ./getopt -a -b admin -c -A 1 -B 2 123qwe -C 3 got option [2]: 'a' ('') got option [3]: 'b' ('') got option [5]: 'c' ('') got option [7]: 'A' ('') arg: '1' got option [9]: 'B' ('') arg: '2' got option [12]: 'C' ('') arg: '3' end up at 10 some argument left, from admin
This time I put the username parameter between - B and - C, and the password parameter between - B and - C.
As you can see, each option has been parsed without missing, and the parameters seem to be correct.
Wait, the optind display location is argv[10], that is to say, admin is argv[10], but it is argv[3] clearly!
And after parsing - C, the end of optind is 12. How can it be reversed?
In order to explain this kind of puzzle, add the following two lines of code after the analysis is completed, and print the command line after the analysis:
1 for (i = 0; i<argc; ++ i) 2 printf ("%s ", argv[i]); 3 4 printf ("\n");
The new program execution output is as follows:
$ ./getopt -a -b admin -c -A 1 -B 2 123qwe -C 3
got option [2]: 'a' ('')
got option [3]: 'b' ('')
got option [5]: 'c' ('')
got option [7]: 'A' ('') arg: '1'
got option [9]: 'B' ('') arg: '2'
got option [12]: 'C' ('') arg: '3'
end up at 10
./getopt -a -b -c -A 1 -B 2 -C 3 admin 123qwe
some argument left, from admin
It turns out that the command line arguments are reordered.
All the options are parsed before the parameters, and the order in which the parameters remain input is arranged after the options.
In this way, you can get the original order of parameter input by traversing through optind, perfect!
It is also found through man 3 getopt that the description is as follows:
By default, getopt() permutes the contents of argv as it scans, so that eventually all the non-options are at the end.
Other mysteries are solved.
In fact, looking back, there is almost no cost for this permute argv parameter, that is, moving the direction of several pointers, which can be said to achieve the maximum benefit with the minimum cost.
Of course, getopt is not omnipotent, for example, when there are duplicate inputs in options, you need to deal with them (if you don't do special processing, the later options will cover the previous ones).