-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgetopt.txt
82 lines (72 loc) · 3.83 KB
/
getopt.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# So, there was a \e[1mgetopt\e[0m in a bygone era which had issues, so they made a \e[1mgetopts\e[0m in 1986 which was shipped with bash.
# In 1995 it was added to the Single Unix Specification (SUS).
# Then a newer one was made for Linux based on a BSD getopt, which they also named getopt. It fixes things in the original
# getopt, and adds features that getopt\e[1ms\e[0m lacks.
# what (new) getopt DOES:
# - you tell it what flags to expect, long or short, and if they require a value
# - you give it all the args
# - it transforms them into a neat list that is easier for you to parse with while/case
# What it does NOT DO:
# - prevent invalid input. it does show an error, but will continue on.
# How it works is iffy to explain without an example:
OPTIONS=$(\e[32mgetopt\e[35;1m -o ab:c -l help\e[0m \e[34;1m-n "$0"\e[0m -- \e[31;1m"$@"\e[0m)
eval set -- "$OPTIONS"
\e[32mgetopt\e[0m \e[36m# calls getopt \o/
\e[35;1m-o ab:c -l help\e[0m \e[36m# expected \e[38;5;208m-o/--options\e[36m and \e[38;5;208m-l/--longoptions\e[36m are supplied here.
\e[36m# an option followed by ':' \e[1mrequires\e[36;22m a value, if no value is passed getopt will not pass it into $OPTIONS
\e[34;1m-n "$0"\e[0m \e[36m# optionally pass the name of the script, used for error messages\e[0m
-- \e[36m# separate options for getopt from whatever was passed to the main script
\e[31;1m"$@"\e[0m \e[36m# positional arguments passed to the main script, as separate strings
# then the eval..$OPTIONS" turns $OPTIONS into $1, $2, ... $n, leaving out flags for missing required values and separating
# everything neatly, so
$(getopt -o abco: -- "$@")
-abo foobar
# becomes
-a -b -o foobar
# Example use in a function:
function foo {
local debug=off
local myvar
options=$(getopt -o dr:h -l help -- "$@")
eval set -- "$options"
while true; do
case "$1" in # case just looks at the first argument. if it's a -d, a var is reset
-d) # and the -d is taken out of args. now it goes back to the start of the loop
debug=ON;
shift
;;
-r) # so the next loop around, it might encounter -r and the same thing happens.
myvar=$2; # but because while (true) it also works if -r comes before -d
shift 2 # note that myvar is set to the Next argument, and 2 items are shifted of remaining args
;;
-h|--help ) # handle both possible options
echo Help text goes here
shift;;
--) # getopt always adds this, so filter it out. and since it's the end of options, you can break
shift
break;;
*) # first time it encounters something not in the cases, it exits the while loop.
break
;;
esac;
done;
# body etc
echo debug: $debug
echo myvar: $myvar
}
# unrelated case notes:
# - every case ends with a double ;;. This can immediately follow the preceding command or statement, like shift;;
# - yes, every case starts with \e[38;5;208mthe-thing-to-match )\e[0m , bash is weird like that.
### PHP ###
# for php the syntax is
$options = getopt(str $shortflags, array $longflags = [], int &$rest_index = null);
# short options are letters, like "abc" for optional -a -b -c flags.
# add a ':' after a flag to make it require a value: "ab:c"
# add 2 '::' to make the value optional (rarely needed)
$options = getopt('abc');
$ script.php -ca
var_export($options); // ['c'=>false, 'a'=>false]
# so check for flag using isset($options['b']) I guess
# NB: getopt stops parsing input at the first non-option (ie something not starting with - or --):
$ script.php -a x -b // ['a'=>false]
$ script.php -a -x -b // ['a'=>false, 'b'=>false]