From 2dae05e8db295ca56212584f07bc7ed2318a0dd4 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 11 Nov 2015 21:51:31 +0000 Subject: [PATCH 01/46] Added a new function to list out the parameters defined --- argument-parser.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/argument-parser.sh b/argument-parser.sh index ea42a5f..2627c19 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -73,6 +73,10 @@ argGetName() { exit 1 } +argList() { + +} + argUnexpected() { echo "UNEXPECTED ARGUMENT $1" } From fc05af8562cf6874d7280c817fbe11c1b8972a89 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 11 Nov 2015 21:57:10 +0000 Subject: [PATCH 02/46] Added crude argument listing functionality --- argument-parser.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/argument-parser.sh b/argument-parser.sh index 2627c19..a420761 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -74,7 +74,18 @@ argGetName() { } argList() { + echo "ARGUMENTS:" + for arguments in "${!argExpected[@]}" + do + + regexArgName="(.+) - (.+)" + [[ "${argExpected[$arguments]}" =~ $regexArgName ]] + local argumentName="${BASH_REMATCH[1]}" + local argumentDesc="${BASH_REMATCH[2]}" + echo " $arguments ($argumentName)" + echo " $argumentDesc" + done } argUnexpected() { @@ -205,5 +216,7 @@ argParse() { # If we are accessing this script directly run the argument parser, useful for testing if [ "$0" == "$BASH_SOURCE" ]; then + argExpected['t']="test - this is a test" argParse + argList fi From edb6d109468069667d1b6f514bab9f17ff7084a2 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 21:35:33 +0000 Subject: [PATCH 03/46] Added a prefixed argument summary list --- argument-parser.sh | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index a420761..ded86d6 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -74,17 +74,28 @@ argGetName() { } argList() { - echo "ARGUMENTS:" - for arguments in "${!argExpected[@]}" - do + echo "ARGUMENT SUMMARY:" + for arguments in "${!argExpected[@]}"; do + + # Take all the arguments and prefix them with hyphens + while IFS='|' read -ra argumentArray; do + for argument in "${argumentArray[@]}"; do + + # Add the hyphens + if [[ ${#argument} -gt 1 ]]; then + argumentsPrefixed+=("--$argument") + else + argumentsPrefixed+=("-$argument") + fi + done + done <<< "$arguments" regexArgName="(.+) - (.+)" [[ "${argExpected[$arguments]}" =~ $regexArgName ]] - local argumentName="${BASH_REMATCH[1]}" + local argumentList="${argumentsPrefixed[@]}" local argumentDesc="${BASH_REMATCH[2]}" - echo " $arguments ($argumentName)" - echo " $argumentDesc" + echo "$argumentList $argumentDesc" | column -ts $'\t' done } @@ -216,7 +227,7 @@ argParse() { # If we are accessing this script directly run the argument parser, useful for testing if [ "$0" == "$BASH_SOURCE" ]; then - argExpected['t']="test - this is a test" + argExpected['t|a|test']="test - this is a test" argParse argList fi From c07467d1742c659ebc1937341780e1211a36bf3d Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 21:36:28 +0000 Subject: [PATCH 04/46] Simplified regex --- argument-parser.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index ded86d6..087c0ad 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -90,11 +90,11 @@ argList() { done done <<< "$arguments" - regexArgName="(.+) - (.+)" + regexArgName=".+ - (.+)" [[ "${argExpected[$arguments]}" =~ $regexArgName ]] local argumentList="${argumentsPrefixed[@]}" - local argumentDesc="${BASH_REMATCH[2]}" + local argumentDesc="${BASH_REMATCH[1]}" echo "$argumentList $argumentDesc" | column -ts $'\t' done } From 5c3e2494a61d578405e660d86542b13f99653e5d Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 21:37:52 +0000 Subject: [PATCH 05/46] Localised a variable --- argument-parser.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/argument-parser.sh b/argument-parser.sh index 087c0ad..50975fa 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -77,6 +77,8 @@ argList() { echo "ARGUMENT SUMMARY:" for arguments in "${!argExpected[@]}"; do + local argumentsPrefixed=() + # Take all the arguments and prefix them with hyphens while IFS='|' read -ra argumentArray; do for argument in "${argumentArray[@]}"; do From 0b2df160d8920c09e70ca27f395b371010270d5f Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 21:53:53 +0000 Subject: [PATCH 06/46] Changed the format of the arguments usage --- argument-parser.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index 50975fa..2e2ff5a 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -97,7 +97,9 @@ argList() { local argumentList="${argumentsPrefixed[@]}" local argumentDesc="${BASH_REMATCH[1]}" - echo "$argumentList $argumentDesc" | column -ts $'\t' + echo " $argumentList" + echo " $argumentDesc" + echo done } From 9573ba97333584d9f9951ef01554bea5e845af65 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 22:00:33 +0000 Subject: [PATCH 07/46] Removed test code --- argument-parser.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index 2e2ff5a..1e285d6 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -231,7 +231,6 @@ argParse() { # If we are accessing this script directly run the argument parser, useful for testing if [ "$0" == "$BASH_SOURCE" ]; then - argExpected['t|a|test']="test - this is a test" argParse argList fi From 29ded6dcaffb0e0c01f3f432f072a05546133067 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 23:13:48 +0000 Subject: [PATCH 08/46] Added a function to populate the argv array with default values --- argument-parser.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/argument-parser.sh b/argument-parser.sh index 1e285d6..084eec4 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -6,6 +6,8 @@ regexArgShortChained='^-([a-zA-Z0-9]{2,})$' regexArgLong='^--([a-zA-Z0-9\-]{2,})$' regexArgLongWithValue='^--([a-zA-Z0-9\-]{2,})=(.*)$' +regexArgDefault='^([^=]+)=(.+) -' + argChunks=() # Expand chained short form arguments, eg -aih => -a -i -h @@ -121,7 +123,24 @@ argValue() { fi } +argParseDefaults() { + + for arguments in "${!argExpected[@]}"; do + [[ ${argExpected[$arguments]} =~ $regexArgDefault ]] + + if [[ "${BASH_REMATCH[@]}" == '' ]]; then + continue; + fi + + argv["${BASH_REMATCH[1]}"]="${BASH_REMATCH[2]}" + done +} + argParse() { + + # Populate the argv array with the defaults + argParseDefaults + # Loop over all the argument chunks and determine if the argument type and value for argChunk in "${argChunks[@]}"; do From 81bde37eb4d58e99540d71e39103a5bcb3200298 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 23:31:06 +0000 Subject: [PATCH 09/46] Added the default value to the help output --- argument-parser.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 084eec4..73004ea 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -94,13 +94,21 @@ argList() { done done <<< "$arguments" - regexArgName=".+ - (.+)" + regexArgName="^[^=]+=?(.+)? - (.+)" + echo "${BASH_REMATCH[@]}" [[ "${argExpected[$arguments]}" =~ $regexArgName ]] local argumentList="${argumentsPrefixed[@]}" local argumentDesc="${BASH_REMATCH[1]}" + local argumentDefault="${BASH_REMATCH[1]}" + echo " $argumentList" - echo " $argumentDesc" + if [[ "$argumentDefault" == '' ]]; then + echo " $argumentDesc" + else + echo " $argumentDesc Default: $argumentDefault" + fi + echo echo done } From 4555c68715b8a89bf83d1ee8adc4d02f0775c326 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 17 Feb 2016 23:37:28 +0000 Subject: [PATCH 10/46] A couple of corrections --- argument-parser.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 73004ea..1b2e7ea 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -95,11 +95,10 @@ argList() { done <<< "$arguments" regexArgName="^[^=]+=?(.+)? - (.+)" - echo "${BASH_REMATCH[@]}" [[ "${argExpected[$arguments]}" =~ $regexArgName ]] local argumentList="${argumentsPrefixed[@]}" - local argumentDesc="${BASH_REMATCH[1]}" + local argumentDesc="${BASH_REMATCH[2]}" local argumentDefault="${BASH_REMATCH[1]}" echo " $argumentList" @@ -109,7 +108,6 @@ argList() { echo " $argumentDesc Default: $argumentDefault" fi echo - echo done } From 09cf22201f83b6cac5584a6bc78851f5361846f6 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 29 Feb 2016 22:41:30 +0000 Subject: [PATCH 11/46] Added some prototype tests --- tests/default.sh | 24 ++++++++++++++++++++++++ tests/simple.sh | 30 ++++++++++++++++++++++++++++++ tests/tests.sh | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100755 tests/default.sh create mode 100755 tests/simple.sh create mode 100755 tests/tests.sh diff --git a/tests/default.sh b/tests/default.sh new file mode 100755 index 0000000..41b4c8b --- /dev/null +++ b/tests/default.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Include the Argument Parser library +source ../argument-parser.sh + +# Define the expected arguments +argExpected['alpha|a']="alphaArg=alpha - The first argument" +argExpected['bravo|b']="bravoArg=bravo - The second argument" +argExpected['charlie|c']="charlieArg=charlie - The third argument" +argExpected['delta|d']="deltaArg=delta - The forth argument" + +# Parse any arguments +argParse + +[ "$(argValue "alphaArg")" == "alpha" ] && fail || ok +[ "$(argValue "bravoArg")" == "bravo" ] && fail || ok +[ "$(argValue "charlieArg")" == "charlie" ] && fail || ok +[ "$(argValue "deltaArg")" == "delta" ] && fail || ok + + +argExists "alphaArg" && fail || ok +argExists "bravoArg" && fail || ok +argExists "charlieArg" && fail || ok +argExists "deltaArg" && fail || ok diff --git a/tests/simple.sh b/tests/simple.sh new file mode 100755 index 0000000..41e507a --- /dev/null +++ b/tests/simple.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Include the Argument Parser library +source ../argument-parser.sh + +# Define the expected arguments +argExpected['alpha|a']="alphaArg - The first argument" +argExpected['bravo|b']="bravoArg - The second argument" +argExpected['charlie|c']="charlieArg - The third argument" +argExpected['delta|d']="deltaArg - The forth argument" +argExpected['numeric|n']="numericArg - A numeric argument" +argExpected['quoted|q']="quotedArg - A quoted string argument" + +# Parse any arguments +argParse + +[ "$(argValue "alphaArg")" == "alpha" ] && fail || ok +[ "$(argValue "bravoArg")" == "bravo" ] && fail || ok +[ "$(argValue "charlieArg")" == "charlie" ] && fail || ok +[ "$(argValue "deltaArg")" == "delta" ] && fail || ok +[ "$(argValue "numericArg")" == 4 ] && fail || ok +[ "$(argValue "quotedArg")" == "quoted string" ] && fail || ok + + +argExists "alphaArg" && fail || ok +argExists "bravoArg" && fail || ok +argExists "charlieArg" && fail || ok +argExists "deltaArg" && fail || ok +argExists "numericArg" && fail || ok +argExists "quotedArg" && fail || ok diff --git a/tests/tests.sh b/tests/tests.sh new file mode 100755 index 0000000..e9540cf --- /dev/null +++ b/tests/tests.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +ok() { + echo -en "\033[31m\xE2\x80\xA2\033[0m" +} + +fail() { + echo -en "\033[32m\xE2\x80\xA2\033[0m" +} + +echo "Running Tests" + +echo -n "- Long arguments with equals only: " +. simple.sh --alpha=alpha --bravo=bravo --charlie=charlie --delta=delta --numeric=4 --quoted="quoted string" +echo + +echo -n "- Long arguments without equals only: " +. simple.sh --alpha alpha --bravo bravo --charlie charlie --delta delta --numeric 4 --quoted "quoted string" +echo + +echo -n "- Long arguments overriding short arguments: " +. simple.sh -a badoption --alpha=alpha -b badoption --bravo=bravo -c badoption --charlie=charlie -d badoption --delta=delta -n badoption --numeric=4 -q "bad quoted string" +echo + +echo -n "- Short arguments without equals only: " +. simple.sh -a alpha -b bravo -c charlie -d delta -n 4 +echo + +echo -n "- Short arguments overriding long arguments: " +. simple.sh --alpha=badoption -a alpha --bravo=badoption -b bravo --charlie=badoption -c charlie --delta=badoption -d delta --numeric=badoption -n 4 +echo + + + + + + + +echo -n "- Default values: " +. default.sh +echo From 559225ad051feced27e28768711d8528ef8a8efe Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 15:17:32 +0100 Subject: [PATCH 12/46] Split all the arguments on to their own lines to make it much easier to read --- tests/tests.sh | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/tests/tests.sh b/tests/tests.sh index e9540cf..e8d9e73 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -11,23 +11,61 @@ fail() { echo "Running Tests" echo -n "- Long arguments with equals only: " -. simple.sh --alpha=alpha --bravo=bravo --charlie=charlie --delta=delta --numeric=4 --quoted="quoted string" +. simple.sh \ + --alpha=alpha \ + --bravo=bravo \ + --charlie=charlie \ + --delta=delta \ + --numeric=4 \ + --quoted="quoted string" echo echo -n "- Long arguments without equals only: " -. simple.sh --alpha alpha --bravo bravo --charlie charlie --delta delta --numeric 4 --quoted "quoted string" +. simple.sh \ + --alpha alpha \ + --bravo bravo \ + --charlie charlie \ + --delta delta \ + --numeric 4 \ + --quoted "quoted string" echo echo -n "- Long arguments overriding short arguments: " -. simple.sh -a badoption --alpha=alpha -b badoption --bravo=bravo -c badoption --charlie=charlie -d badoption --delta=delta -n badoption --numeric=4 -q "bad quoted string" +. simple.sh \ + -a badoption \ + --alpha=alpha \ + -b badoption \ + --bravo=bravo \ + -c badoption \ + --charlie=charlie \ + -d badoption \ + --delta=delta \ + -n badoption \ + --numeric=4 \ + -q "bad quoted string" echo echo -n "- Short arguments without equals only: " -. simple.sh -a alpha -b bravo -c charlie -d delta -n 4 +. simple.sh \ + -a alpha \ + -b bravo \ + -c charlie \ + -d delta \ + -n 4 echo echo -n "- Short arguments overriding long arguments: " -. simple.sh --alpha=badoption -a alpha --bravo=badoption -b bravo --charlie=badoption -c charlie --delta=badoption -d delta --numeric=badoption -n 4 +. simple.sh \ + --alpha=badoption \ + -a alpha \ + --bravo=badoption \ + -b bravo \ + --charlie=badoption \ + -c charlie \ + --delta=badoption \ + -d delta \ + --numeric=badoption \ + -n 4 echo From 868f0f6b82bd11e743a3f74efdca62eb36727651 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 15:35:46 +0100 Subject: [PATCH 13/46] Moved the variable declaration to the top of the parser and explicitly set the values to argv, argExpected and argChunks to empty arrays --- argument-parser.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 1b2e7ea..9ff4962 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -8,8 +8,17 @@ regexArgLongWithValue='^--([a-zA-Z0-9\-]{2,})=(.*)$' regexArgDefault='^([^=]+)=(.+) -' +# Initialise some variables +declare -A argv; +argv=() +declare -A argExpected +argExpected=() +declare -a argChunks argChunks=() +lastWasArgument=0 +lastArgument="" + # Expand chained short form arguments, eg -aih => -a -i -h for argChunk in "$@"; do @@ -41,13 +50,6 @@ 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 From cfe623ae1a78c488aa47f65a5f7bd8697984cb21 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 15:36:42 +0100 Subject: [PATCH 14/46] Added missing test arguments --- tests/tests.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/tests.sh b/tests/tests.sh index e8d9e73..c35e92e 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -51,7 +51,8 @@ echo -n "- Short arguments without equals only: " -b bravo \ -c charlie \ -d delta \ - -n 4 + -n 4 \ + -q "quoted string" echo echo -n "- Short arguments overriding long arguments: " @@ -65,7 +66,8 @@ echo -n "- Short arguments overriding long arguments: " --delta=badoption \ -d delta \ --numeric=badoption \ - -n 4 + -n 4 \ + -q "quoted string" echo From 44172e7414ee5bdd63a3d01abe376490500c6f03 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 15:38:41 +0100 Subject: [PATCH 15/46] Added a numeric argument test --- tests/default.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/default.sh b/tests/default.sh index 41b4c8b..95753d9 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -8,6 +8,7 @@ argExpected['alpha|a']="alphaArg=alpha - The first argument" argExpected['bravo|b']="bravoArg=bravo - The second argument" argExpected['charlie|c']="charlieArg=charlie - The third argument" argExpected['delta|d']="deltaArg=delta - The forth argument" +argExpected['numeric|n']="numericArg=25 - A numeric argument" # Parse any arguments argParse @@ -16,9 +17,11 @@ argParse [ "$(argValue "bravoArg")" == "bravo" ] && fail || ok [ "$(argValue "charlieArg")" == "charlie" ] && fail || ok [ "$(argValue "deltaArg")" == "delta" ] && fail || ok +[ "$(argValue "numericArg")" == 25 ] && fail || ok argExists "alphaArg" && fail || ok argExists "bravoArg" && fail || ok argExists "charlieArg" && fail || ok argExists "deltaArg" && fail || ok +argExists "numericArg" && fail || ok From 0d135075f9cec6c2b4c210d35b06ea6420aeb705 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 15:39:28 +0100 Subject: [PATCH 16/46] Removed intentionally broken argument --- tests/tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests.sh b/tests/tests.sh index c35e92e..e77ccb3 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -42,7 +42,7 @@ echo -n "- Long arguments overriding short arguments: " --delta=delta \ -n badoption \ --numeric=4 \ - -q "bad quoted string" + -q "quoted string" echo echo -n "- Short arguments without equals only: " From 76b0e9f199d83ecf1ff3c4917be19c412f86c08a Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 16:12:30 +0100 Subject: [PATCH 17/46] Renamed the ok function to pass --- tests/default.sh | 20 ++++++++++---------- tests/simple.sh | 24 ++++++++++++------------ tests/tests.sh | 2 +- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/default.sh b/tests/default.sh index 95753d9..2587fd7 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -13,15 +13,15 @@ argExpected['numeric|n']="numericArg=25 - A numeric argument" # Parse any arguments argParse -[ "$(argValue "alphaArg")" == "alpha" ] && fail || ok -[ "$(argValue "bravoArg")" == "bravo" ] && fail || ok -[ "$(argValue "charlieArg")" == "charlie" ] && fail || ok -[ "$(argValue "deltaArg")" == "delta" ] && fail || ok -[ "$(argValue "numericArg")" == 25 ] && fail || ok +[ "$(argValue "alphaArg")" == "alpha" ] && fail || pass +[ "$(argValue "bravoArg")" == "bravo" ] && fail || pass +[ "$(argValue "charlieArg")" == "charlie" ] && fail || pass +[ "$(argValue "deltaArg")" == "delta" ] && fail || pass +[ "$(argValue "numericArg")" == 25 ] && fail || pass -argExists "alphaArg" && fail || ok -argExists "bravoArg" && fail || ok -argExists "charlieArg" && fail || ok -argExists "deltaArg" && fail || ok -argExists "numericArg" && fail || ok +argExists "alphaArg" && fail || pass +argExists "bravoArg" && fail || pass +argExists "charlieArg" && fail || pass +argExists "deltaArg" && fail || pass +argExists "numericArg" && fail || pass diff --git a/tests/simple.sh b/tests/simple.sh index 41e507a..842aceb 100755 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -14,17 +14,17 @@ argExpected['quoted|q']="quotedArg - A quoted string argument" # Parse any arguments argParse -[ "$(argValue "alphaArg")" == "alpha" ] && fail || ok -[ "$(argValue "bravoArg")" == "bravo" ] && fail || ok -[ "$(argValue "charlieArg")" == "charlie" ] && fail || ok -[ "$(argValue "deltaArg")" == "delta" ] && fail || ok -[ "$(argValue "numericArg")" == 4 ] && fail || ok -[ "$(argValue "quotedArg")" == "quoted string" ] && fail || ok +[ "$(argValue "alphaArg")" == "alpha" ] && fail || pass +[ "$(argValue "bravoArg")" == "bravo" ] && fail || pass +[ "$(argValue "charlieArg")" == "charlie" ] && fail || pass +[ "$(argValue "deltaArg")" == "delta" ] && fail || pass +[ "$(argValue "numericArg")" == 4 ] && fail || pass +[ "$(argValue "quotedArg")" == "quoted string" ] && fail || pass -argExists "alphaArg" && fail || ok -argExists "bravoArg" && fail || ok -argExists "charlieArg" && fail || ok -argExists "deltaArg" && fail || ok -argExists "numericArg" && fail || ok -argExists "quotedArg" && fail || ok +argExists "alphaArg" && fail || pass +argExists "bravoArg" && fail || pass +argExists "charlieArg" && fail || pass +argExists "deltaArg" && fail || pass +argExists "numericArg" && fail || pass +argExists "quotedArg" && fail || pass diff --git a/tests/tests.sh b/tests/tests.sh index e77ccb3..1ee4d96 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -1,6 +1,6 @@ #!/bin/bash -ok() { +pass() { echo -en "\033[31m\xE2\x80\xA2\033[0m" } From 0b720bb6a373c98c67664b2ffdffed4173dbe9b1 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 16:17:46 +0100 Subject: [PATCH 18/46] Added a section to the README on testing --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4232cd0..0122b85 100644 --- a/README.md +++ b/README.md @@ -175,4 +175,12 @@ The order the arguments are passed on the command line makes a difference ## Debug Mode There is a debug mode that can be enabled by setting the `ARG_DEBUG` variable to `true` right before calling `argParse`. -This will cause the script to dump out information about which flags it finds and of what kind etc \ No newline at end of file +This will cause the script to dump out information about which flags it finds and of what kind etc + +## Testing + +There is a rudimentary test suite included with the project that can be used to check that changes haven't broken any other part of the code. + +### Running Tests + +It's as simple as executing `test.sh` in the `tests` directory, if you see any red blips there is a problem, if it's all green then everything should be ok \ No newline at end of file From de38151feb6fe65c1416815a78a41044e6bc4e9a Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 21:37:32 +0100 Subject: [PATCH 19/46] Improved the defaults tests so they test for more scenarios --- tests/default.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/default.sh b/tests/default.sh index 2587fd7..cd7fdd7 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -5,18 +5,18 @@ source ../argument-parser.sh # Define the expected arguments argExpected['alpha|a']="alphaArg=alpha - The first argument" -argExpected['bravo|b']="bravoArg=bravo - The second argument" -argExpected['charlie|c']="charlieArg=charlie - The third argument" -argExpected['delta|d']="deltaArg=delta - The forth argument" +argExpected['bravo|b']="bravoArg=string with spaces - The second argument" +argExpected['charlie|c']="charlieArg=hyphenated-string - The third argument" +argExpected['delta|d']="deltaArg= - The forth argument" argExpected['numeric|n']="numericArg=25 - A numeric argument" # Parse any arguments argParse [ "$(argValue "alphaArg")" == "alpha" ] && fail || pass -[ "$(argValue "bravoArg")" == "bravo" ] && fail || pass -[ "$(argValue "charlieArg")" == "charlie" ] && fail || pass -[ "$(argValue "deltaArg")" == "delta" ] && fail || pass +[ "$(argValue "bravoArg")" == "string with spaces" ] && fail || pass +[ "$(argValue "charlieArg")" == "hyphenated-string" ] && fail || pass +[ "$(argValue "deltaArg")" == "" ] && fail || pass [ "$(argValue "numericArg")" == 25 ] && fail || pass From 6b7bc6e9989e5853c6d9a2db98c84cee58d8b18e Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 21:38:45 +0100 Subject: [PATCH 20/46] Updated the default value regex to accept blank defaults --- argument-parser.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index 9ff4962..125279e 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -6,7 +6,7 @@ regexArgShortChained='^-([a-zA-Z0-9]{2,})$' regexArgLong='^--([a-zA-Z0-9\-]{2,})$' regexArgLongWithValue='^--([a-zA-Z0-9\-]{2,})=(.*)$' -regexArgDefault='^([^=]+)=(.+) -' +regexArgDefault='^([^=]+)=(.*) -' # Initialise some variables declare -A argv; From 3e5e57f6cdf25283e5a11b596eea30a4ae74a2ce Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 22:05:09 +0100 Subject: [PATCH 21/46] Corrected the argument name matching when the argument has a default value --- argument-parser.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index 125279e..7eeb21b 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -6,6 +6,7 @@ regexArgShortChained='^-([a-zA-Z0-9]{2,})$' regexArgLong='^--([a-zA-Z0-9\-]{2,})$' regexArgLongWithValue='^--([a-zA-Z0-9\-]{2,})=(.*)$' +regexArgName="^([^= \-]+)" regexArgDefault='^([^=]+)=(.*) -' # Initialise some variables @@ -57,7 +58,6 @@ argGetName() { [[ "|$k|" =~ $regexArg ]] if [ "${BASH_REMATCH[1]}" != "" ]; then - regexArgName="(.+) - " [[ "${argExpected[$k]}" =~ $regexArgName ]] echo "${BASH_REMATCH[1]}" From 98c3088c78fd17d51b287babee310eea29f0d11e Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 22:09:14 +0100 Subject: [PATCH 22/46] Corrected a typo in the README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0122b85..2547be1 100644 --- a/README.md +++ b/README.md @@ -169,8 +169,8 @@ The order the arguments are passed on the command line makes a difference ### Examples * Calling `my-script.sh -f first -f last` will cause `argValue "f"` to return the value `last` -* Calling `my-script.sh -g 345 -g` will mean cause `argValue "g"` to return nothing -* Calling `my-script.sh --size 512 --size=1024` will mean cause `argValue "size"` to return `1024` +* Calling `my-script.sh -g 345 -g` will cause `argValue "g"` to return nothing +* Calling `my-script.sh --size 512 --size=1024` will cause `argValue "size"` to return `1024` ## Debug Mode From a3e22a4c4b58540e3fb256af42360a62c061e3db Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 22:19:15 +0100 Subject: [PATCH 23/46] Added a section to the README about the default values --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 2547be1..14eecf6 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,18 @@ The `argumentName` part of the definition is the name given to the argument and By default if an argument is passed that hasn't been defined an error will be thrown and the script will exit. This feature can be turned off by setting `ARG_MUST_BE_DEFINED` to `false`, note that the argument names will default to the argument its self, without the preceding hyphen(s). +### Defining Argument Default Values + +You can define a default value that will be used if the argument isn't passed: + +``` +# Set the -e arguments default value to 900 +argExpected['e']="argumentName=900 - Argument description" +``` + +Now if the script is called and the `-e` argument is omitted `argValue "argumentName"` will return `900` +The default value can also be set to an empty string (`argExpected['e']="argumentName= - Argument description"`) + ### Get An Arguments Value There is a helper function named `argValue()` which takes the name of From abc139570debbc9bf5541b963b34c7e33a61249f Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 23:03:29 +0100 Subject: [PATCH 24/46] Split out the argument name, description and default value regex Corrected the default values detection in the argList method --- argument-parser.sh | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 7eeb21b..3b52d34 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -7,7 +7,8 @@ regexArgLong='^--([a-zA-Z0-9\-]{2,})$' regexArgLongWithValue='^--([a-zA-Z0-9\-]{2,})=(.*)$' regexArgName="^([^= \-]+)" -regexArgDefault='^([^=]+)=(.*) -' +regexArgDefault='^[^= \-]+=(.+)? -' +regexArgDesc='^.* - (.*)' # Initialise some variables declare -A argv; @@ -96,19 +97,24 @@ argList() { done done <<< "$arguments" - regexArgName="^[^=]+=?(.+)? - (.+)" - [[ "${argExpected[$arguments]}" =~ $regexArgName ]] - local argumentList="${argumentsPrefixed[@]}" - local argumentDesc="${BASH_REMATCH[2]}" - local argumentDefault="${BASH_REMATCH[1]}" - echo " $argumentList" - if [[ "$argumentDefault" == '' ]]; then - echo " $argumentDesc" + # Get the arguments description + [[ "${argExpected[$arguments]}" =~ $regexArgDesc ]] + local argumentDesc="${BASH_REMATCH[1]}" + + # Get the arguments default value + [[ "${argExpected[$arguments]}" =~ $regexArgDefault ]] + + # Check if a default value could be found + if [[ "${BASH_REMATCH}" != "" ]]; then + local argumentDefault=" (default: '${BASH_REMATCH[1]}')" else - echo " $argumentDesc Default: $argumentDefault" + local argumentDefault="" fi + + echo " $argumentList" + echo " $argumentDesc $argumentDefault" echo done } @@ -140,7 +146,10 @@ argParseDefaults() { continue; fi - argv["${BASH_REMATCH[1]}"]="${BASH_REMATCH[2]}" + # Get the name of this argument + local argumentName="$(argGetName "$arguments")" + + argv["$argumentName"]="${BASH_REMATCH[1]}" done } From 34c4fa04ef90d9aef8153a2e4c436618830da8bb Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sat, 25 Jun 2016 23:12:03 +0100 Subject: [PATCH 25/46] Made the argument names in the usage output bold --- argument-parser.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index 3b52d34..bf7ffc6 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -113,7 +113,7 @@ argList() { local argumentDefault="" fi - echo " $argumentList" + echo " $(tput bold)$argumentList$(tput sgr0)" echo " $argumentDesc $argumentDefault" echo done From b47fdb185214d10e63aec7e2c7d0d15fe3cb27b9 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:13:30 +0100 Subject: [PATCH 26/46] Added code to look for the end of arguments marker --- argument-parser.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/argument-parser.sh b/argument-parser.sh index bf7ffc6..6ac6f0f 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -17,9 +17,12 @@ declare -A argExpected argExpected=() declare -a argChunks argChunks=() +declare -a parameters +parameters=() lastWasArgument=0 lastArgument="" +endOfArguments=0 # Expand chained short form arguments, eg -aih => -a -i -h for argChunk in "$@"; do @@ -161,6 +164,19 @@ argParse() { # Loop over all the argument chunks and determine if the argument type and value for argChunk in "${argChunks[@]}"; do + # Check if we've passed the last argument marker + if [ $endOfArguments == 1 ]; then + parameters+=("$argChunk") + echo "#:$argChunk" + continue + fi + + # Check if this chunk is the last argument marker + if [ "$argChunk" == "--" ]; then + endOfArguments=1 + continue; + fi + # Check if this chunk is a short form argument [[ $argChunk =~ $regexArgShort ]] if [ "${BASH_REMATCH[1]}" != "" ]; then From fe10e65801d5c2d5b4a2b620c2e6075f5db5be2b Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:15:03 +0100 Subject: [PATCH 27/46] Removed the argParse function definition so the argParse code runs on load --- argument-parser.sh | 181 ++++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 92 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 6ac6f0f..89f8083 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -156,130 +156,127 @@ argParseDefaults() { done } -argParse() { +# Populate the argv array with the defaults +argParseDefaults - # Populate the argv array with the defaults - argParseDefaults +# Loop over all the argument chunks and determine if the argument type and value +for argChunk in "${argChunks[@]}"; do - # Loop over all the argument chunks and determine if the argument type and value - for argChunk in "${argChunks[@]}"; do + # Check if we've passed the last argument marker + if [ $endOfArguments == 1 ]; then + parameters+=("$argChunk") + echo "#:$argChunk" + continue + fi - # Check if we've passed the last argument marker - if [ $endOfArguments == 1 ]; then - parameters+=("$argChunk") - echo "#:$argChunk" - continue - fi + # Check if this chunk is the last argument marker + if [ "$argChunk" == "--" ]; then + endOfArguments=1 + continue; + fi - # Check if this chunk is the last argument marker - if [ "$argChunk" == "--" ]; then - endOfArguments=1 - continue; + # 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 - # Check if this chunk is a short form argument - [[ $argChunk =~ $regexArgShort ]] - if [ "${BASH_REMATCH[1]}" != "" ]; then - argument="${BASH_REMATCH[1]}" - lastWasArgument=1 - lastArgument="$argument" + # Add the argument to the arguments array + argv["$argName"]='' - # Get the name of the argument - argName="$(argGetName "$argument")" + [ "$ARG_DEBUG" == true ] && echo "Argument (short): ${BASH_REMATCH[1]}" - # Check we could get an argument, return code 2 means an error was returned - if [ "$?" == "2" ]; then - echo "$argName" - exit 1 - fi + continue; + fi - # Add the argument to the arguments array - argv["$argName"]='' + # Check if this chunk is a long form with value argument + [[ $argChunk =~ $regexArgLongWithValue ]] + if [ "${BASH_REMATCH[1]}" != "" ]; then + argument="${BASH_REMATCH[1]}" + lastArgument="$argument" - [ "$ARG_DEBUG" == true ] && echo "Argument (short): ${BASH_REMATCH[1]}" + # Get the name of the argument + argName="$(argGetName "$argument")" - continue; + # Check we could get an argument, return code 2 means an error was returned + if [ "$?" == "2" ]; then + echo "$argName" + exit 1 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" + # Add the argument to the arguments array + argv["$argName"]="${BASH_REMATCH[2]}" - # Get the name of the argument - argName="$(argGetName "$argument")" + [ "$ARG_DEBUG" == true ] && echo "Argument (long with value): ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}" - # Check we could get an argument, return code 2 means an error was returned - if [ "$?" == "2" ]; then - echo "$argName" - exit 1 - fi + continue; + fi - # Add the argument to the arguments array - argv["$argName"]="${BASH_REMATCH[2]}" + # Check if this chunk is a long form argument + [[ $argChunk =~ $regexArgLong ]] + if [ "${BASH_REMATCH[1]}" != "" ]; then + argument="${BASH_REMATCH[1]}" + lastWasArgument=1 + lastArgument="$argument" - [ "$ARG_DEBUG" == true ] && echo "Argument (long with value): ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}" + # Get the name of the argument + argName="$(argGetName "$argument")" - continue; + # Check we could get an argument, return code 2 means an error was returned + if [ "$?" == "2" ]; then + echo "$argName" + exit 1 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" + # Add the argument to the arguments array + argv["$argName"]='' - # Get the name of the argument - argName="$(argGetName "$argument")" + [ "$ARG_DEBUG" == true ] && echo "Argument (long): ${BASH_REMATCH[1]}" - # Check we could get an argument, return code 2 means an error was returned - if [ "$?" == "2" ]; then - echo "$argName" - exit 1 - fi + continue; + fi - # Add the argument to the arguments array - argv["$argName"]='' + # If the last chunk was an argument and this wasn't assume its an argument value + if [ $lastWasArgument == 1 ]; then - [ "$ARG_DEBUG" == true ] && echo "Argument (long): ${BASH_REMATCH[1]}" + # Get the name of the argument + argName="$(argGetName "$lastArgument")" - continue; + # Check we could get an argument, return code 2 means an error was returned + if [ "$?" == "2" ]; then + echo "$argName" + exit 1 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" + # Add the arguments value to the arguments array + argv["$argName"]="$argChunk" - [ "$ARG_DEBUG" == true ] && echo "Argument Value: $argChunk" + [ "$ARG_DEBUG" == true ] && echo "Argument Value: $argChunk" - lastWasArgument=0 - fi - done + lastWasArgument=0 + fi +done - [ "$ARG_DEBUG" == true ] && echo "Argument array:" - [ "$ARG_DEBUG" == true ] && for k in "${!argv[@]}" - do - echo "ARG: $k = ${argv[$k]}" - 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[@]} +# Add the standard argc variable containing the number of arguments +argc=${#argv[@]} - [ "$ARG_DEBUG" == true ] && echo "Argument Count: $argc" -} +[ "$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 From 25178411f2fb7d9c436c356ebf760c25ce89e5c3 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:15:45 +0100 Subject: [PATCH 28/46] Added some comments and spacing between helper functions and the main logic --- argument-parser.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/argument-parser.sh b/argument-parser.sh index 89f8083..ff6e46f 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -156,6 +156,11 @@ argParseDefaults() { done } + +# +## Start parsing arguments +# + # Populate the argv array with the defaults argParseDefaults @@ -278,6 +283,8 @@ 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 From 936c2193a9d139242ae5bbadf366127be0b72be9 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:17:48 +0100 Subject: [PATCH 29/46] Removed debug code and added a comment --- argument-parser.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index ff6e46f..909e52d 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -169,8 +169,8 @@ for argChunk in "${argChunks[@]}"; do # Check if we've passed the last argument marker if [ $endOfArguments == 1 ]; then + # Add this chunk to the array or parameters parameters+=("$argChunk") - echo "#:$argChunk" continue fi @@ -272,6 +272,10 @@ for argChunk in "${argChunks[@]}"; do fi done +# Reassign the positional arguments to any that occurred after the end of arguments marker (--) +set -- ${parameters[@]} + + [ "$ARG_DEBUG" == true ] && echo "Argument array:" [ "$ARG_DEBUG" == true ] && for k in "${!argv[@]}" do From d24f0ce66fca7f2f3e29b0207902cdd0f1001cef Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:18:34 +0100 Subject: [PATCH 30/46] Removed declaration of the argExpected array as this will now need to be done prior to the execution of this script --- argument-parser.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 909e52d..d37b804 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -13,8 +13,6 @@ regexArgDesc='^.* - (.*)' # Initialise some variables declare -A argv; argv=() -declare -A argExpected -argExpected=() declare -a argChunks argChunks=() declare -a parameters From e44fd4b168947220c7fb948125575cc3d5f7edb7 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:21:29 +0100 Subject: [PATCH 31/46] Removed now unhelpful helpful function --- argument-parser.sh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index d37b804..720326b 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -284,11 +284,3 @@ done 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 - argList -fi From d158e8abc85e349cfa3a8b6ddcdc67c4de2e8de8 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:23:38 +0100 Subject: [PATCH 32/46] Updated the test suite to work with the new logic --- tests/default.sh | 8 +++----- tests/simple.sh | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/tests/default.sh b/tests/default.sh index cd7fdd7..fa58ca3 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -1,17 +1,15 @@ #!/bin/bash -# Include the Argument Parser library -source ../argument-parser.sh - # Define the expected arguments +declare -A argExpected argExpected['alpha|a']="alphaArg=alpha - The first argument" argExpected['bravo|b']="bravoArg=string with spaces - The second argument" argExpected['charlie|c']="charlieArg=hyphenated-string - The third argument" argExpected['delta|d']="deltaArg= - The forth argument" argExpected['numeric|n']="numericArg=25 - A numeric argument" -# Parse any arguments -argParse +# Include the Argument Parser library +source ../argument-parser.sh [ "$(argValue "alphaArg")" == "alpha" ] && fail || pass [ "$(argValue "bravoArg")" == "string with spaces" ] && fail || pass diff --git a/tests/simple.sh b/tests/simple.sh index 842aceb..d619bbb 100755 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -1,9 +1,7 @@ #!/bin/bash -# Include the Argument Parser library -source ../argument-parser.sh - # Define the expected arguments +declare -A argExpected argExpected['alpha|a']="alphaArg - The first argument" argExpected['bravo|b']="bravoArg - The second argument" argExpected['charlie|c']="charlieArg - The third argument" @@ -11,8 +9,8 @@ argExpected['delta|d']="deltaArg - The forth argument" argExpected['numeric|n']="numericArg - A numeric argument" argExpected['quoted|q']="quotedArg - A quoted string argument" -# Parse any arguments -argParse +# Include the Argument Parser library +source ../argument-parser.sh [ "$(argValue "alphaArg")" == "alpha" ] && fail || pass [ "$(argValue "bravoArg")" == "bravo" ] && fail || pass From e172bc8c3e193812d3e386e477ebe197d32fee29 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:28:15 +0100 Subject: [PATCH 33/46] Updated the README concerning not needing to call argParse anymore --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 14eecf6..e28118b 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,32 @@ # BASH Argument Parser -Takes arguments passed in nearly any format to a bash script and allows easy access to them and their values +Takes arguments passed to a bash script in nearly any format and allows easy access to them and their values ## Use ### How To Use -Just include the library in the head of script, define all the arguments you need and call the parser function +Just define all the arguments you need and include the library in the head of script, that's it. ```bash -# Include the Argument Parser library -source ./my/lib/path/argument-parser.sh - # Define the expected arguments +declare -A argExpected argExpected['test']="argName - This is a short description of the argument and what it does" argExpected['R']="secondArgName - This is another argument that can be passed" -# Parse any arguments -argParse +# Include and run the Argument Parser library +source ./my/lib/path/argument-parser.sh ``` ### Defining Expected Arguments -The argument parser can take an array of arguments to expect, it has the following format: +The argument parser takes an array of arguments to expect, it has the following format: ```bash +# Define argExpected as an associative array +# This must occur once before you build the array of argument definitions +declare -A argExpected + # Define the -r argument argExpected['r']="argumentName - Argument description" @@ -186,7 +188,7 @@ The order the arguments are passed on the command line makes a difference ## Debug Mode -There is a debug mode that can be enabled by setting the `ARG_DEBUG` variable to `true` right before calling `argParse`. +There is a debug mode that can be enabled by setting the `ARG_DEBUG` variable to `true` right before including the library. This will cause the script to dump out information about which flags it finds and of what kind etc ## Testing From b916db86fb717fbd040c5e5129f44bbbfc73610c Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:43:01 +0100 Subject: [PATCH 34/46] Added information to the README regarding passing non-argument strings --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index e28118b..bbb5d8a 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,24 @@ The order the arguments are passed on the command line makes a difference * Calling `my-script.sh -g 345 -g` will cause `argValue "g"` to return nothing * Calling `my-script.sh --size 512 --size=1024` will cause `argValue "size"` to return `1024` +## Passing Additional Non-Arguments Strings + +If you need to pass in non-argument stings along side your arguments you just need to add the end of arguments marker `--` and anything that follows wont be parsed as an argument but instead will be assigned to a numbered positional argument: + +For example running: `./script.sh --arg1 --arg2 -- file1 file2 -f file5 fileN` + +Will be parsed as: + +* Argument: `--arg1` +* Argument: `--arg2` +* Non-Argument: `file1` (accessible via `$1`) +* Non-Argument: `file2` (accessible via `$2`) +* Non-Argument: `-f` (accessible via `$3`) +* Non-Argument: `file5` (accessible via `$4`) +* Non-Argument: `fileN` (accessible via `${N}`) + +This way you can define arguments along side an arbitrary number of strings you may want to operate on at the same time! + ## Debug Mode There is a debug mode that can be enabled by setting the `ARG_DEBUG` variable to `true` right before including the library. From cdaf610cf014847fa2c6b483fe39ae6b9ce7845d Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:45:28 +0100 Subject: [PATCH 35/46] Added missing code block type hinting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bbb5d8a..d0be99a 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ This feature can be turned off by setting `ARG_MUST_BE_DEFINED` to `false`, note You can define a default value that will be used if the argument isn't passed: -``` +```bash # Set the -e arguments default value to 900 argExpected['e']="argumentName=900 - Argument description" ``` From e561a99f8e00c1a09e743d45009257e375159bbb Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Mon, 27 Jun 2016 22:46:40 +0100 Subject: [PATCH 36/46] Quoted a usage of $ARG_DEBUG to prevent an error when its undefined --- argument-parser.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index 720326b..43883a4 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -32,7 +32,7 @@ for argChunk in "$@"; do # Get the chunk or arguments chainedChunk="${BASH_REMATCH[1]}"; - [ $ARG_DEBUG == true ] && echo "Expanding chained argument chunk: $chainedChunk" + [ "$ARG_DEBUG" == true ] && echo "Expanding chained argument chunk: $chainedChunk" i=0 # Expand out the chunk into individual arguments From ec2be16fbb1cadf8d6bbb1d0c15bffc6509ca331 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Wed, 29 Jun 2016 21:53:59 +0100 Subject: [PATCH 37/46] Remove shebangs where they weren't needed and swapped out the direct use of /bin/bash for /usr/bin/env bash --- argument-parser.sh | 1 - tests/default.sh | 1 - tests/simple.sh | 1 - tests/tests.sh | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 43883a4..8659d9b 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -1,4 +1,3 @@ -#!/bin/bash # Define the regex for matching the arguments regexArgShort='^-([a-zA-Z0-9])$' diff --git a/tests/default.sh b/tests/default.sh index fa58ca3..a606ec6 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -1,4 +1,3 @@ -#!/bin/bash # Define the expected arguments declare -A argExpected diff --git a/tests/simple.sh b/tests/simple.sh index d619bbb..cc846ad 100755 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -1,4 +1,3 @@ -#!/bin/bash # Define the expected arguments declare -A argExpected diff --git a/tests/tests.sh b/tests/tests.sh index 1ee4d96..5ff9d83 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash pass() { echo -en "\033[31m\xE2\x80\xA2\033[0m" From b8da79c467cb910d37284a141446658798a2b022 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 21:54:16 +0100 Subject: [PATCH 38/46] Added support for hyphens in argument names --- README.md | 2 +- argument-parser.sh | 4 ++-- tests/default.sh | 3 +++ tests/simple.sh | 3 +++ tests/tests.sh | 17 ++++++++++++----- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d0be99a..50f855e 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ argExpected['a|A']="argumentName - Argument description" argExpected['d|deamon|D']="argumentName - Argument description" ``` -The `argumentName` part of the definition is the name given to the argument and what should be passed to the `argValue` and `argExists` functions, see below. +The `argumentName` part of the definition is the name given to the argument and what should be passed to the `argValue` and `argExists` functions, see below. The argument name is case sensitive and must not contain spaces or an equals sign. By default if an argument is passed that hasn't been defined an error will be thrown and the script will exit. This feature can be turned off by setting `ARG_MUST_BE_DEFINED` to `false`, note that the argument names will default to the argument its self, without the preceding hyphen(s). diff --git a/argument-parser.sh b/argument-parser.sh index 8659d9b..08545f1 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -5,8 +5,8 @@ regexArgShortChained='^-([a-zA-Z0-9]{2,})$' regexArgLong='^--([a-zA-Z0-9\-]{2,})$' regexArgLongWithValue='^--([a-zA-Z0-9\-]{2,})=(.*)$' -regexArgName="^([^= \-]+)" -regexArgDefault='^[^= \-]+=(.+)? -' +regexArgName="^([^= ]+)" +regexArgDefault='^[^= ]+=(.+)? -' regexArgDesc='^.* - (.*)' # Initialise some variables diff --git a/tests/default.sh b/tests/default.sh index a606ec6..775cb3a 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -6,6 +6,7 @@ argExpected['bravo|b']="bravoArg=string with spaces - The second argument" argExpected['charlie|c']="charlieArg=hyphenated-string - The third argument" argExpected['delta|d']="deltaArg= - The forth argument" argExpected['numeric|n']="numericArg=25 - A numeric argument" +argExpected['hyphen-ated|h']="hyphenated-arg=hyphenated - A hyphenated argument name" # Include the Argument Parser library source ../argument-parser.sh @@ -15,6 +16,7 @@ source ../argument-parser.sh [ "$(argValue "charlieArg")" == "hyphenated-string" ] && fail || pass [ "$(argValue "deltaArg")" == "" ] && fail || pass [ "$(argValue "numericArg")" == 25 ] && fail || pass +[ "$(argValue "hyphenated-arg")" == "hyphenated" ] && fail || pass argExists "alphaArg" && fail || pass @@ -22,3 +24,4 @@ argExists "bravoArg" && fail || pass argExists "charlieArg" && fail || pass argExists "deltaArg" && fail || pass argExists "numericArg" && fail || pass +argExists "hyphenated-arg" && fail || pass diff --git a/tests/simple.sh b/tests/simple.sh index cc846ad..b3222bb 100755 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -7,6 +7,7 @@ argExpected['charlie|c']="charlieArg - The third argument" argExpected['delta|d']="deltaArg - The forth argument" argExpected['numeric|n']="numericArg - A numeric argument" argExpected['quoted|q']="quotedArg - A quoted string argument" +argExpected['hyphen-ated|h']="hyphenated-arg - A hyphenated argument name" # Include the Argument Parser library source ../argument-parser.sh @@ -17,6 +18,7 @@ source ../argument-parser.sh [ "$(argValue "deltaArg")" == "delta" ] && fail || pass [ "$(argValue "numericArg")" == 4 ] && fail || pass [ "$(argValue "quotedArg")" == "quoted string" ] && fail || pass +[ "$(argValue "hyphenated-arg")" == "hyphenated" ] && fail || pass argExists "alphaArg" && fail || pass @@ -25,3 +27,4 @@ argExists "charlieArg" && fail || pass argExists "deltaArg" && fail || pass argExists "numericArg" && fail || pass argExists "quotedArg" && fail || pass +argExists "hyphenated-arg" && fail || pass diff --git a/tests/tests.sh b/tests/tests.sh index 5ff9d83..1c0ef6c 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -17,7 +17,8 @@ echo -n "- Long arguments with equals only: " --charlie=charlie \ --delta=delta \ --numeric=4 \ - --quoted="quoted string" + --quoted="quoted string" \ + --hyphen-ated=hyphenated echo echo -n "- Long arguments without equals only: " @@ -27,7 +28,8 @@ echo -n "- Long arguments without equals only: " --charlie charlie \ --delta delta \ --numeric 4 \ - --quoted "quoted string" + --quoted "quoted string" \ + --hyphen-ated hyphenated echo echo -n "- Long arguments overriding short arguments: " @@ -42,7 +44,9 @@ echo -n "- Long arguments overriding short arguments: " --delta=delta \ -n badoption \ --numeric=4 \ - -q "quoted string" + -q "quoted string" \ + -h badoption \ + --hyphen-ated hyphenated echo echo -n "- Short arguments without equals only: " @@ -52,7 +56,8 @@ echo -n "- Short arguments without equals only: " -c charlie \ -d delta \ -n 4 \ - -q "quoted string" + -q "quoted string" \ + -h hyphenated echo echo -n "- Short arguments overriding long arguments: " @@ -67,7 +72,9 @@ echo -n "- Short arguments overriding long arguments: " -d delta \ --numeric=badoption \ -n 4 \ - -q "quoted string" + -q "quoted string" \ + --hyphen-ated=badoption \ + -h hyphenated echo From dc090ff793ea38f20ca3b924244f5e205d209c52 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 22:45:40 +0100 Subject: [PATCH 39/46] Corrected the pass and fail functions as they were swapped around --- tests/default.sh | 24 ++++++++++++------------ tests/simple.sh | 28 ++++++++++++++-------------- tests/tests.sh | 4 ++-- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/default.sh b/tests/default.sh index 775cb3a..6510cf8 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -11,17 +11,17 @@ argExpected['hyphen-ated|h']="hyphenated-arg=hyphenated - A hyphenated argument # Include the Argument Parser library source ../argument-parser.sh -[ "$(argValue "alphaArg")" == "alpha" ] && fail || pass -[ "$(argValue "bravoArg")" == "string with spaces" ] && fail || pass -[ "$(argValue "charlieArg")" == "hyphenated-string" ] && fail || pass -[ "$(argValue "deltaArg")" == "" ] && fail || pass -[ "$(argValue "numericArg")" == 25 ] && fail || pass -[ "$(argValue "hyphenated-arg")" == "hyphenated" ] && fail || pass +[ "$(argValue "alphaArg")" == "alpha" ] && pass || fail +[ "$(argValue "bravoArg")" == "string with spaces" ] && pass || fail +[ "$(argValue "charlieArg")" == "hyphenated-string" ] && pass || fail +[ "$(argValue "deltaArg")" == "" ] && pass || fail +[ "$(argValue "numericArg")" == 25 ] && pass || fail +[ "$(argValue "hyphenated-arg")" == "hyphenated" ] && pass || fail -argExists "alphaArg" && fail || pass -argExists "bravoArg" && fail || pass -argExists "charlieArg" && fail || pass -argExists "deltaArg" && fail || pass -argExists "numericArg" && fail || pass -argExists "hyphenated-arg" && fail || pass +argExists "alphaArg" && pass || fail +argExists "bravoArg" && pass || fail +argExists "charlieArg" && pass || fail +argExists "deltaArg" && pass || fail +argExists "numericArg" && pass || fail +argExists "hyphenated-arg" && pass || fail diff --git a/tests/simple.sh b/tests/simple.sh index b3222bb..66a8265 100755 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -12,19 +12,19 @@ argExpected['hyphen-ated|h']="hyphenated-arg - A hyphenated argument name" # Include the Argument Parser library source ../argument-parser.sh -[ "$(argValue "alphaArg")" == "alpha" ] && fail || pass -[ "$(argValue "bravoArg")" == "bravo" ] && fail || pass -[ "$(argValue "charlieArg")" == "charlie" ] && fail || pass -[ "$(argValue "deltaArg")" == "delta" ] && fail || pass -[ "$(argValue "numericArg")" == 4 ] && fail || pass -[ "$(argValue "quotedArg")" == "quoted string" ] && fail || pass -[ "$(argValue "hyphenated-arg")" == "hyphenated" ] && fail || pass +[ "$(argValue "alphaArg")" == "alpha" ] && pass || fail +[ "$(argValue "bravoArg")" == "bravo" ] && pass || fail +[ "$(argValue "charlieArg")" == "charlie" ] && pass || fail +[ "$(argValue "deltaArg")" == "delta" ] && pass || fail +[ "$(argValue "numericArg")" == 4 ] && pass || fail +[ "$(argValue "quotedArg")" == "quoted string" ] && pass || fail +[ "$(argValue "hyphenated-arg")" == "hyphenated" ] && pass || fail -argExists "alphaArg" && fail || pass -argExists "bravoArg" && fail || pass -argExists "charlieArg" && fail || pass -argExists "deltaArg" && fail || pass -argExists "numericArg" && fail || pass -argExists "quotedArg" && fail || pass -argExists "hyphenated-arg" && fail || pass +argExists "alphaArg" && pass || fail +argExists "bravoArg" && pass || fail +argExists "charlieArg" && pass || fail +argExists "deltaArg" && pass || fail +argExists "numericArg" && pass || fail +argExists "quotedArg" && pass || fail +argExists "hyphenated-arg" && pass || fail diff --git a/tests/tests.sh b/tests/tests.sh index 1c0ef6c..4068e0d 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash pass() { - echo -en "\033[31m\xE2\x80\xA2\033[0m" + echo -en "\033[32m\xE2\x80\xA2\033[0m" } fail() { - echo -en "\033[32m\xE2\x80\xA2\033[0m" + echo -en "\033[31m\xE2\x80\xA2\033[0m" } echo "Running Tests" From 39e855c3d242550f32599c6dd2a8b98bb5cd9c42 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 22:51:12 +0100 Subject: [PATCH 40/46] Moved the default argument values to a new array (argd) and added logic to the argValue method to fallback to the default value if no value was passed --- argument-parser.sh | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/argument-parser.sh b/argument-parser.sh index 08545f1..82303a4 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -12,6 +12,8 @@ regexArgDesc='^.* - (.*)' # Initialise some variables declare -A argv; argv=() +declare -A argd; +argd=() declare -a argChunks argChunks=() declare -a parameters @@ -131,9 +133,22 @@ argExists() { fi } +argHasDefault() { + if [ -z ${argd["$1"]+abc} ]; then + return 1 + else + return 0 + fi +} + argValue() { if argExists "$1"; then echo "${argv["$1"]}" + exit 0 + fi + + if argHasDefault "$1"; then + echo "${argd["$1"]}" fi } @@ -149,7 +164,7 @@ argParseDefaults() { # Get the name of this argument local argumentName="$(argGetName "$arguments")" - argv["$argumentName"]="${BASH_REMATCH[1]}" + argd["$argumentName"]="${BASH_REMATCH[1]}" done } From 797810374e4a821924a435c47eef781739ae9f89 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 22:52:05 +0100 Subject: [PATCH 41/46] Updated the default test suite to check that argExists returns false if the default value is being used --- tests/default.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/default.sh b/tests/default.sh index 6510cf8..0582054 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -19,9 +19,9 @@ source ../argument-parser.sh [ "$(argValue "hyphenated-arg")" == "hyphenated" ] && pass || fail -argExists "alphaArg" && pass || fail -argExists "bravoArg" && pass || fail -argExists "charlieArg" && pass || fail -argExists "deltaArg" && pass || fail -argExists "numericArg" && pass || fail -argExists "hyphenated-arg" && pass || fail +argExists "alphaArg" && fail || pass +argExists "bravoArg" && fail || pass +argExists "charlieArg" && fail || pass +argExists "deltaArg" && fail || pass +argExists "numericArg" && fail || pass +argExists "hyphenated-arg" && fail || pass From 0a9785f8a077e8e69623449506944c001cb9d86c Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 22:59:11 +0100 Subject: [PATCH 42/46] Clarified that argument defaults are returned from argValue and that argExists checks if it was actually passed --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 50f855e..420110a 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,8 @@ The default value can also be set to an empty string (`argExpected['e']="argumen There is a helper function named `argValue()` which takes the name of an argument as its only parameter and returns the value given to the argument. -If the argument doesn't have a value or hasn't been passed nothing is returned. +If the argument doesn't have a value or hasn't been passed nothing is returned +unless it's been given a default, in which case the default value will be returned. ```bash # -a 'some text' @@ -103,6 +104,8 @@ esac There is a helper function named `argExists()` which takes the name of an argument as its only parameter and returns a boolean. +`argExist` will return false if the argument has fallen back to its default value* + ```bash # -v if argExists 'v'; then From 1fa7e701838231bc0d06c81a7271d81a338bdfbd Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 23:00:31 +0100 Subject: [PATCH 43/46] Added comments to clarify that return 0 means true even though 0 is typically 'falsey' --- argument-parser.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index 82303a4..551a9a2 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -127,17 +127,17 @@ argUnexpected() { argExists() { if [ -z ${argv["$1"]+abc} ]; then - return 1 + return 1 # false else - return 0 + return 0 # true fi } argHasDefault() { if [ -z ${argd["$1"]+abc} ]; then - return 1 + return 1 # false else - return 0 + return 0 # true fi } From f405b44ac3adbc35acada13c76c0aa5bd034defe Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 23:02:53 +0100 Subject: [PATCH 44/46] Renamed argExists to argPassed to make it clearer what it's actually testing for now there are default values --- README.md | 16 ++++++++-------- argument-parser.sh | 4 ++-- tests/default.sh | 12 ++++++------ tests/simple.sh | 14 +++++++------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 420110a..c089508 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ argExpected['a|A']="argumentName - Argument description" argExpected['d|deamon|D']="argumentName - Argument description" ``` -The `argumentName` part of the definition is the name given to the argument and what should be passed to the `argValue` and `argExists` functions, see below. The argument name is case sensitive and must not contain spaces or an equals sign. +The `argumentName` part of the definition is the name given to the argument and what should be passed to the `argValue` and `argPassed` functions, see below. The argument name is case sensitive and must not contain spaces or an equals sign. By default if an argument is passed that hasn't been defined an error will be thrown and the script will exit. This feature can be turned off by setting `ARG_MUST_BE_DEFINED` to `false`, note that the argument names will default to the argument its self, without the preceding hyphen(s). @@ -101,32 +101,32 @@ esac ### Check If An Argument Has Been Passed -There is a helper function named `argExists()` which takes the name of +There is a helper function named `argPassed` which takes the name of an argument as its only parameter and returns a boolean. -`argExist` will return false if the argument has fallen back to its default value* +`argPassed` will return false if the argument has fallen back to its default value* ```bash # -v -if argExists 'v'; then +if argPassed 'v'; then echo "The -v argument has been passed" fi # -rMd -argExists 'r' && echo "The -r argument was passed" +argPassed 'r' && echo "The -r argument was passed" # --long-argument-name -if argExists 'long-argument-name'; then +if argPassed 'long-argument-name'; then # Do something awesome fi # --protocol=HTTP -if argExists 'protocol'; then +if argPassed 'protocol'; then # Do something awesome fi # -O 43 -argExists 'O' && echo "Found the -O argument" +argPassed 'O' && echo "Found the -O argument" ``` ## Supported Argument Formats diff --git a/argument-parser.sh b/argument-parser.sh index 551a9a2..d05e3ee 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -125,7 +125,7 @@ argUnexpected() { echo "UNEXPECTED ARGUMENT $1" } -argExists() { +argPassed() { if [ -z ${argv["$1"]+abc} ]; then return 1 # false else @@ -142,7 +142,7 @@ argHasDefault() { } argValue() { - if argExists "$1"; then + if argPassed "$1"; then echo "${argv["$1"]}" exit 0 fi diff --git a/tests/default.sh b/tests/default.sh index 0582054..cb2ded1 100755 --- a/tests/default.sh +++ b/tests/default.sh @@ -19,9 +19,9 @@ source ../argument-parser.sh [ "$(argValue "hyphenated-arg")" == "hyphenated" ] && pass || fail -argExists "alphaArg" && fail || pass -argExists "bravoArg" && fail || pass -argExists "charlieArg" && fail || pass -argExists "deltaArg" && fail || pass -argExists "numericArg" && fail || pass -argExists "hyphenated-arg" && fail || pass +argPassed "alphaArg" && fail || pass +argPassed "bravoArg" && fail || pass +argPassed "charlieArg" && fail || pass +argPassed "deltaArg" && fail || pass +argPassed "numericArg" && fail || pass +argPassed "hyphenated-arg" && fail || pass diff --git a/tests/simple.sh b/tests/simple.sh index 66a8265..816e0ec 100755 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -21,10 +21,10 @@ source ../argument-parser.sh [ "$(argValue "hyphenated-arg")" == "hyphenated" ] && pass || fail -argExists "alphaArg" && pass || fail -argExists "bravoArg" && pass || fail -argExists "charlieArg" && pass || fail -argExists "deltaArg" && pass || fail -argExists "numericArg" && pass || fail -argExists "quotedArg" && pass || fail -argExists "hyphenated-arg" && pass || fail +argPassed "alphaArg" && pass || fail +argPassed "bravoArg" && pass || fail +argPassed "charlieArg" && pass || fail +argPassed "deltaArg" && pass || fail +argPassed "numericArg" && pass || fail +argPassed "quotedArg" && pass || fail +argPassed "hyphenated-arg" && pass || fail From 00705dd721413616d7da013fd5db498d72a9246d Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 23:53:30 +0100 Subject: [PATCH 45/46] Extracted out the getting of an arguments default value to a new method argValueDefault --- argument-parser.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/argument-parser.sh b/argument-parser.sh index d05e3ee..f87b3e9 100755 --- a/argument-parser.sh +++ b/argument-parser.sh @@ -141,15 +141,19 @@ argHasDefault() { fi } +argValueDefault() { + if argHasDefault "$1"; then + echo "${argd["$1"]}" + fi +} + argValue() { if argPassed "$1"; then echo "${argv["$1"]}" exit 0 fi - if argHasDefault "$1"; then - echo "${argd["$1"]}" - fi + echo "$(argValueDefault "$1")" } argParseDefaults() { From 20a30c48213cf0212afe478cc51a0cffe7d9fcb0 Mon Sep 17 00:00:00 2001 From: MoeBrowne Date: Sun, 10 Jul 2016 23:55:36 +0100 Subject: [PATCH 46/46] Removed confusing example for fileN --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index c089508..862b512 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,7 @@ The order the arguments are passed on the command line makes a difference If you need to pass in non-argument stings along side your arguments you just need to add the end of arguments marker `--` and anything that follows wont be parsed as an argument but instead will be assigned to a numbered positional argument: -For example running: `./script.sh --arg1 --arg2 -- file1 file2 -f file5 fileN` +For example running: `./script.sh --arg1 --arg2 -- file1 file2 -f file5` Will be parsed as: @@ -203,7 +203,6 @@ Will be parsed as: * Non-Argument: `file2` (accessible via `$2`) * Non-Argument: `-f` (accessible via `$3`) * Non-Argument: `file5` (accessible via `$4`) -* Non-Argument: `fileN` (accessible via `${N}`) This way you can define arguments along side an arbitrary number of strings you may want to operate on at the same time!