forked from moebrowne/bash-argument-parser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathargument-parser.sh
More file actions
executable file
·205 lines (154 loc) · 4.65 KB
/
argument-parser.sh
File metadata and controls
executable file
·205 lines (154 loc) · 4.65 KB
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/bin/bash
# Define the regex for matching the arguments
regexArgShort='^-([a-zA-Z0-9])$'
regexArgShortChained='^-([a-zA-Z0-9]{2,})$'
regexArgLong='^--([a-zA-Z0-9\-]{2,})$'
regexArgLongWithValue='^--([a-zA-Z0-9\-]{2,})=(.*)$'
argChunks=()
# Expand chained short form arguments, eg -aih => -a -i -h
for argChunk in "$@"; do
# See if this argument is a chained short form argument
[[ $argChunk =~ $regexArgShortChained ]]
if [ "${BASH_REMATCH[1]}" != "" ]; then
# Get the chunk or arguments
chainedChunk="${BASH_REMATCH[1]}";
[ $ARG_DEBUG == true ] && echo "Expanding chained argument chunk: $chainedChunk"
i=0
# Expand out the chunk into individual arguments
while (( i++ < ${#chainedChunk} )); do
# Get just the argument on its own
argumentIsolated="${chainedChunk:$i-1:1}"
# Add the isolated argument to the argument chunk array
argChunks+=("-$argumentIsolated")
done
continue;
fi
# Add the argument to the argument array
argChunks+=("$argChunk")
done
[ "$ARG_DEBUG" == true ] && echo "Expanded argument list: ${argChunks[@]}"
# Initialise some variables
declare -A argv
lastWasArgument=0
lastArgument=""
declare -A argExpected
argGetName() {
for k in "${!argExpected[@]}"
do
regexArg="\|($1)\|"
[[ "|$k|" =~ $regexArg ]]
if [ "${BASH_REMATCH[1]}" != "" ]; then
regexArgName="(.+) - "
[[ "${argExpected[$k]}" =~ $regexArgName ]]
echo "${BASH_REMATCH[1]}"
exit 0
fi
done
# Check if the argument must be defined
if [ "$ARG_MUST_BE_DEFINED" != false ]; then
argUnexpected "$argChunk"
exit 2
fi
# Default to using the argument as the name
echo "$1"
exit 1
}
argUnexpected() {
echo "UNEXPECTED ARGUMENT $1"
}
argExists() {
if [ -z ${argv["$1"]+abc} ]; then
return 1
else
return 0
fi
}
argValue() {
if argExists "$1"; then
echo "${argv["$1"]}"
fi
}
argParse() {
# Loop over all the argument chunks and determine if the argument type and value
for argChunk in "${argChunks[@]}"; do
# Check if this chunk is a short form argument
[[ $argChunk =~ $regexArgShort ]]
if [ "${BASH_REMATCH[1]}" != "" ]; then
argument="${BASH_REMATCH[1]}"
lastWasArgument=1
lastArgument="$argument"
# Get the name of the argument
argName="$(argGetName "$argument")"
# Check we could get an argument, return code 2 means an error was returned
if [ "$?" == "2" ]; then
echo "$argName"
exit 1
fi
# Add the argument to the arguments array
argv["$argName"]=''
[ "$ARG_DEBUG" == true ] && echo "Argument (short): ${BASH_REMATCH[1]}"
continue;
fi
# Check if this chunk is a long form with value argument
[[ $argChunk =~ $regexArgLongWithValue ]]
if [ "${BASH_REMATCH[1]}" != "" ]; then
argument="${BASH_REMATCH[1]}"
lastArgument="$argument"
# Get the name of the argument
argName="$(argGetName "$argument")"
# Check we could get an argument, return code 2 means an error was returned
if [ "$?" == "2" ]; then
echo "$argName"
exit 1
fi
# Add the argument to the arguments array
argv["$argName"]="${BASH_REMATCH[2]}"
[ "$ARG_DEBUG" == true ] && echo "Argument (long with value): ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}"
continue;
fi
# Check if this chunk is a long form argument
[[ $argChunk =~ $regexArgLong ]]
if [ "${BASH_REMATCH[1]}" != "" ]; then
argument="${BASH_REMATCH[1]}"
lastWasArgument=1
lastArgument="$argument"
# Get the name of the argument
argName="$(argGetName "$argument")"
# Check we could get an argument, return code 2 means an error was returned
if [ "$?" == "2" ]; then
echo "$argName"
exit 1
fi
# Add the argument to the arguments array
argv["$argName"]=''
[ "$ARG_DEBUG" == true ] && echo "Argument (long): ${BASH_REMATCH[1]}"
continue;
fi
# If the last chunk was an argument and this wasn't assume its an argument value
if [ $lastWasArgument == 1 ]; then
# Get the name of the argument
argName="$(argGetName "$lastArgument")"
# Check we could get an argument, return code 2 means an error was returned
if [ "$?" == "2" ]; then
echo "$argName"
exit 1
fi
# Add the arguments value to the arguments array
argv["$argName"]="$argChunk"
[ "$ARG_DEBUG" == true ] && echo "Argument Value: $argChunk"
lastWasArgument=0
fi
done
[ "$ARG_DEBUG" == true ] && echo "Argument array:"
[ "$ARG_DEBUG" == true ] && for k in "${!argv[@]}"
do
echo "ARG: $k = ${argv[$k]}"
done
# Add the standard argc variable containing the number of arguments
argc=${#argv[@]}
[ "$ARG_DEBUG" == true ] && echo "Argument Count: $argc"
}
# If we are accessing this script directly run the argument parser, useful for testing
if [ "$0" == "$BASH_SOURCE" ]; then
argParse
fi