Skip to content

Commit 97070d8

Browse files
committed
Merge branch 'develop'
2 parents 0eb6e51 + 77c4fc7 commit 97070d8

File tree

2 files changed

+225
-1
lines changed

2 files changed

+225
-1
lines changed

README.md

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,114 @@
1-
# BASH Argument Parser
1+
# BASH Argument Parser
2+
3+
Takes arguments passed in nearly any format to a bash script and allows easy access to them and their values
4+
5+
## Use
6+
7+
### Get An Arguments Value
8+
9+
There is a helper function named `argValue()` which takes the name of
10+
an argument as its only parameter and returns the value given to the argument.
11+
12+
If the argument doesn't have a value or hasn't been passed nothing is returned.
13+
14+
```bash
15+
16+
# -a 'some text'
17+
if [ "$(argValue "a")" == 'some text' ]; then
18+
# Do something awesome
19+
fi
20+
21+
# --debug 3
22+
DEBUG_LEVEL="$(argValue "debug")" # 3
23+
24+
# -R 0
25+
[ "$(argValue "R")" == "0" ] && echo "Recursive depth 0"
26+
27+
# -aXb 'cookie'
28+
BISCUIT="$(argValue "b")" # 'cookie'
29+
30+
# -g 'hello' -G 'world'
31+
ALPHA="$(argValue "g")" # 'hello'
32+
BRAVO="$(argValue "G")" # 'world'
33+
34+
# -S d
35+
case $(argValue 'S') in
36+
a) echo "something" ;;
37+
b) echo "something" ;;
38+
c) echo "something" ;;
39+
d) echo "darkside" ;;
40+
esac
41+
42+
```
43+
44+
### Check If An Argument Has Been Passed
45+
46+
There is a helper function named `argExists()` which takes the name of
47+
an argument as its only parameter and returns a boolean.
48+
49+
```bash
50+
51+
# -v
52+
if argExists 'v'; then
53+
echo "The -v argument has been passed"
54+
fi
55+
56+
# -rMd
57+
argExists 'r' && echo "The -r argument was passed"
58+
59+
# --long-argument-name
60+
if argExists 'long-argument-name'; then
61+
# Do something awesome
62+
fi
63+
64+
# -O 43
65+
argExists 'r' && echo "Found the -O argument"
66+
67+
```
68+
69+
## Supported Argument Formats
70+
71+
### Short Form
72+
73+
```bash
74+
-a
75+
-X
76+
-b somevalue
77+
-c 38
78+
-d "some value with spaces"
79+
-e "some value with
80+
newlines"
81+
```
82+
83+
### Long Form
84+
85+
```bash
86+
--debug
87+
--test mode0
88+
--test "all the code"
89+
--Case-Sensitive true
90+
--long-parameter
91+
--newline "
92+
"
93+
```
94+
95+
### Chained Short Form Arguments
96+
97+
```bash
98+
-aih # Equivalent to -a -i -h
99+
-dav 4 # Equivalent to -d -a -v 4
100+
```
101+
102+
## Argument Order
103+
104+
The order the arguments are passed on the command line makes a difference
105+
106+
### Examples
107+
108+
* Calling `my-script.sh -f first -f last` will cause `${args["f"]}` to have the value `last`
109+
* Calling `my-script.sh -g 345 -g` will mean cause `${args["g"]}` to be blank
110+
111+
## Debug Mode
112+
113+
There is a debug mode that can be enabled by setting the `ARG_DEBUG` variable at the top of the script to `true`.
114+
This will cause the script to dump out information about which flags it finds and of what kind etc

argument-parser.sh

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/bin/bash
2+
3+
# Define the regex for matching the arguments
4+
regexArgShort='^-([a-zA-Z])$'
5+
regexArgShortChained='^-([a-zA-Z]{2,})$'
6+
regexArgLong='^--([a-zA-Z\-]{2,})$'
7+
8+
argChunks=()
9+
10+
ARG_DEBUG=false
11+
12+
# Expand chained short form arguments, eg -aih => -a -i -h
13+
for argChunk in "$@"; do
14+
15+
# See if this argument is a chained short form argument
16+
[[ $argChunk =~ $regexArgShortChained ]]
17+
if [ "${BASH_REMATCH[1]}" != "" ]; then
18+
19+
# Get the chunk or arguments
20+
chainedChunk="${BASH_REMATCH[1]}";
21+
22+
[ $ARG_DEBUG == true ] && echo "Expanding chained argument chunk: $chainedChunk"
23+
24+
i=0
25+
# Expand out the chunk into individual arguments
26+
while (( i++ < ${#chainedChunk} )); do
27+
28+
# Get just the argument on its own
29+
argumentIsolated="${chainedChunk:$i-1:1}"
30+
31+
# Add the isolated argument to the argument chunk array
32+
argChunks+=("-$argumentIsolated")
33+
done
34+
continue;
35+
fi
36+
37+
# Add the argument to the argument array
38+
argChunks+=("$argChunk")
39+
done
40+
41+
[ $ARG_DEBUG == true ] && echo "Expanded argument list: ${argChunks[@]}"
42+
43+
# Initialise some variables
44+
declare -A args
45+
lastWasArgument=0
46+
lastArgument=""
47+
48+
# Loop over all the argument chunks and determine if the argument type and value
49+
for argChunk in "${argChunks[@]}"; do
50+
51+
# Check if this chunk is a short form argument
52+
[[ $argChunk =~ $regexArgShort ]]
53+
if [ "${BASH_REMATCH[1]}" != "" ]; then
54+
argument="${BASH_REMATCH[1]}"
55+
lastWasArgument=1
56+
lastArgument="$argument"
57+
58+
# Add the argument to the arguments array
59+
args["${BASH_REMATCH[1]}"]=''
60+
61+
[ $ARG_DEBUG == true ] && echo "Argument (short): ${BASH_REMATCH[1]}"
62+
63+
continue;
64+
fi
65+
66+
# Check if this chunk is a long form argument
67+
[[ $argChunk =~ $regexArgLong ]]
68+
if [ "${BASH_REMATCH[1]}" != "" ]; then
69+
argument="${BASH_REMATCH[1]}"
70+
lastWasArgument=1
71+
lastArgument="$argument"
72+
73+
# Add the argument to the arguments array
74+
args["${BASH_REMATCH[1]}"]=''
75+
76+
[ $ARG_DEBUG == true ] && echo "Argument (long): ${BASH_REMATCH[1]}"
77+
78+
continue;
79+
fi
80+
81+
# If the last chunk was an argument and this wasn't assume its an argument value
82+
if [ $lastWasArgument == 1 ]; then
83+
84+
# Add the arguments value to the arguments array
85+
args["$lastArgument"]="$argChunk"
86+
87+
[ $ARG_DEBUG == true ] && echo "Argument Value: $argChunk"
88+
89+
lastWasArgument=0
90+
fi
91+
done
92+
93+
[ $ARG_DEBUG == true ] && echo "Argument array:"
94+
[ $ARG_DEBUG == true ] && for k in "${!args[@]}"
95+
do
96+
echo "ARG: $k = ${args[$k]}"
97+
done
98+
99+
argExists() {
100+
if [ -z ${args["$1"]+abc} ]; then
101+
return 1
102+
else
103+
return 0
104+
fi
105+
}
106+
107+
argValue() {
108+
if argExists "$1"; then
109+
echo "${args["$1"]}"
110+
fi
111+
}

0 commit comments

Comments
 (0)