Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
a simple way to parse shell script arguments
#!/bin/sh
#
# a simple way to parse shell script arguments
#
# please edit and use to your hearts content
#
ENVIRONMENT="dev"
DB_PATH="/data/db"
function usage()
{
echo "if this was a real script you would see something useful here"
echo ""
echo "./simple_args_parsing.sh"
echo "\t-h --help"
echo "\t--environment=$ENVIRONMENT"
echo "\t--db-path=$DB_PATH"
echo ""
}
while [ "$1" != "" ]; do
PARAM=`echo $1 | awk -F= '{print $1}'`
VALUE=`echo $1 | awk -F= '{print $2}'`
case $PARAM in
-h | --help)
usage
exit
;;
--environment)
ENVIRONMENT=$VALUE
;;
--db-path)
DB_PATH=$VALUE
;;
*)
echo "ERROR: unknown parameter \"$PARAM\""
usage
exit 1
;;
esac
shift
done
echo "ENVIRONMENT is $ENVIRONMENT";
echo "DB_PATH is $DB_PATH";
@hypersoft

This comment has been minimized.

Show comment Hide comment
@hypersoft

hypersoft Jan 26, 2013

👎 You've complicated a really simple task..

printfx() {

    TEMP=`getopt -o hbrkwels:c:v:f:p: --long help,write,keep,reset,bold,format:,script:,color:,print: -n "$FUNCNAME" -- "$@"`

    if [ $? != 0 ] ; then return 1 ; fi

    eval set -- "$TEMP";

    local format='%s\n' escape='-E' line='-n' script clear='tput sgr0';

    while [[ ${1:0:1} == - ]]; do
        [[ $1 =~ ^-h|--help ]] && {
            cat <<-EOF
            USAGE: $FUNCNAME [OPTIONS] [TEXT]

            OPTIONS

              -s  Adds a line of text to tput script
              -c  Adds a line of text to tput script that sets the foreground
                  color
              -b  Adds a line of text to tput script that activates emboldened
                  text
              -f  Sets the final printf format
              -w  Forces an immediate write of tput script
              -p  Immediately prints data to standard out
              -e  Enabled backslash interpretation in immediate print operations
              -l  Enables line output in immediate print operations
              -k  disables terminal reset on return
              -r  Forces an immediate reset of terminal settings
              -v  Adds multiple lines of script from a shell variable label

              --script  Same as -s
              --color   Same as -c
              --bold    Same as -b
              --format  Same as -f
              --write   Same as -w
              --print   Same as -p
              --keep    Same as -k
              --reset   Same as -r

            EOF
            return;
        };

        [[ $1 == -- ]] && { shift; break; };
        [[ $1 == -l ]] && { line=''; shift 1; continue; };
        [[ $1 =~ ^-s|--script$ ]] && { script+="$2"$'\n'; shift 2; continue; };
        [[ $1 =~ ^-c|--color$ ]] && { script+="setf $2"$'\n'; shift 2; continue; };
        [[ $1 =~ ^-b|--bold$ ]] && { script+="bold"$'\n'; shift 1; continue; };
        [[ $1 =~ ^-f|--format$ ]] && { format="${2}"; shift 2; continue; };
        [[ $1 =~ ^-w|--write$ ]] && { tput -S <<<"$script"; script=''; shift 1; continue; };
        [[ $1 =~ ^-p|--print$ ]] && { echo $escape $line "${2}"; escape='-E' line='-n'; shift 2; continue; };
        [[ $1 =~ ^-k|--keep$ ]] && { clear='true'; shift 1; continue; };
        [[ $1 =~ ^-r|--reset$ ]] && { tput sgr0; shift 1; continue; };
        [[ $1 =~ ^-v ]] && { script+="${!2}"$'\n'; shift 2; continue; };
        [[ $1 =~ ^-e ]] && { escape=$1; shift 1; continue; };

        break;
    done

    echo $format;
    tput -S <<<"$script";
    (( $# )) && printf "$format" "$@";
    $clear;

}

👎 You've complicated a really simple task..

printfx() {

    TEMP=`getopt -o hbrkwels:c:v:f:p: --long help,write,keep,reset,bold,format:,script:,color:,print: -n "$FUNCNAME" -- "$@"`

    if [ $? != 0 ] ; then return 1 ; fi

    eval set -- "$TEMP";

    local format='%s\n' escape='-E' line='-n' script clear='tput sgr0';

    while [[ ${1:0:1} == - ]]; do
        [[ $1 =~ ^-h|--help ]] && {
            cat <<-EOF
            USAGE: $FUNCNAME [OPTIONS] [TEXT]

            OPTIONS

              -s  Adds a line of text to tput script
              -c  Adds a line of text to tput script that sets the foreground
                  color
              -b  Adds a line of text to tput script that activates emboldened
                  text
              -f  Sets the final printf format
              -w  Forces an immediate write of tput script
              -p  Immediately prints data to standard out
              -e  Enabled backslash interpretation in immediate print operations
              -l  Enables line output in immediate print operations
              -k  disables terminal reset on return
              -r  Forces an immediate reset of terminal settings
              -v  Adds multiple lines of script from a shell variable label

              --script  Same as -s
              --color   Same as -c
              --bold    Same as -b
              --format  Same as -f
              --write   Same as -w
              --print   Same as -p
              --keep    Same as -k
              --reset   Same as -r

            EOF
            return;
        };

        [[ $1 == -- ]] && { shift; break; };
        [[ $1 == -l ]] && { line=''; shift 1; continue; };
        [[ $1 =~ ^-s|--script$ ]] && { script+="$2"$'\n'; shift 2; continue; };
        [[ $1 =~ ^-c|--color$ ]] && { script+="setf $2"$'\n'; shift 2; continue; };
        [[ $1 =~ ^-b|--bold$ ]] && { script+="bold"$'\n'; shift 1; continue; };
        [[ $1 =~ ^-f|--format$ ]] && { format="${2}"; shift 2; continue; };
        [[ $1 =~ ^-w|--write$ ]] && { tput -S <<<"$script"; script=''; shift 1; continue; };
        [[ $1 =~ ^-p|--print$ ]] && { echo $escape $line "${2}"; escape='-E' line='-n'; shift 2; continue; };
        [[ $1 =~ ^-k|--keep$ ]] && { clear='true'; shift 1; continue; };
        [[ $1 =~ ^-r|--reset$ ]] && { tput sgr0; shift 1; continue; };
        [[ $1 =~ ^-v ]] && { script+="${!2}"$'\n'; shift 2; continue; };
        [[ $1 =~ ^-e ]] && { escape=$1; shift 1; continue; };

        break;
    done

    echo $format;
    tput -S <<<"$script";
    (( $# )) && printf "$format" "$@";
    $clear;

}
@perepechaev

This comment has been minimized.

Show comment Hide comment
@perepechaev

perepechaev Jul 18, 2013

I think that it is better to replace https://gist.github.com/jehiah/855086#file-simple_args_parsing-sh-L26

VALUE=`echo $1 | sed 's/^[^=]*=//g'`

sample:
/bin/sh myscript --host=localhost --uri="/some/uri/?debug=1"

I think that it is better to replace https://gist.github.com/jehiah/855086#file-simple_args_parsing-sh-L26

VALUE=`echo $1 | sed 's/^[^=]*=//g'`

sample:
/bin/sh myscript --host=localhost --uri="/some/uri/?debug=1"

@geoff-codes

This comment has been minimized.

Show comment Hide comment
@geoff-codes

geoff-codes Nov 2, 2013

@hypersoft: I really don't see how your code is any simpler... it is much less readable; and significantly less portable. This gist would appear to be intended as a shell script; not a bash script; and while the original does have one bashism, it seems like a trivial oversight (should be just usage() rather than function usage(). Your code includes using GNU getopt; herestrings, and many, many bash-only features that make it completely unsuited for any type of portable shell script.

@hypersoft: I really don't see how your code is any simpler... it is much less readable; and significantly less portable. This gist would appear to be intended as a shell script; not a bash script; and while the original does have one bashism, it seems like a trivial oversight (should be just usage() rather than function usage(). Your code includes using GNU getopt; herestrings, and many, many bash-only features that make it completely unsuited for any type of portable shell script.

@brunodix

This comment has been minimized.

Show comment Hide comment
@brunodix

brunodix Feb 4, 2014

Thanks, works even on Git Bash on Windows.

brunodix commented Feb 4, 2014

Thanks, works even on Git Bash on Windows.

@cfollet

This comment has been minimized.

Show comment Hide comment
@cfollet

cfollet May 24, 2016

Thank you for this. But why you didn't use$0 in order to retrieve the script name ?

cfollet commented May 24, 2016

Thank you for this. But why you didn't use$0 in order to retrieve the script name ?

@diemol

This comment has been minimized.

Show comment Hide comment
@diemol

diemol Sep 30, 2016

Shouldn't line https://gist.github.com/jehiah/855086#file-simple_args_parsing-sh-L44 be shift 2?
I am trying it and the parameters are shifted one by one, when (I think) the loop expects them to move two by two.

Anyway, thanks for this, saves a bunch of time 👍

diemol commented Sep 30, 2016

Shouldn't line https://gist.github.com/jehiah/855086#file-simple_args_parsing-sh-L44 be shift 2?
I am trying it and the parameters are shifted one by one, when (I think) the loop expects them to move two by two.

Anyway, thanks for this, saves a bunch of time 👍

@matejak

This comment has been minimized.

Show comment Hide comment
@matejak

matejak Dec 7, 2016

Better than writing the parsing code is having one generated and that's the reason why I have started the argbash project here on Github. Keeping the usage function up-to-date and having support for positional arguments are some of the obvious benefits.
There is even an online bash 3.0+ compatible parsing code generator at https://argbash.io/generate

matejak commented Dec 7, 2016

Better than writing the parsing code is having one generated and that's the reason why I have started the argbash project here on Github. Keeping the usage function up-to-date and having support for positional arguments are some of the obvious benefits.
There is even an online bash 3.0+ compatible parsing code generator at https://argbash.io/generate

@stancufm

This comment has been minimized.

Show comment Hide comment
@stancufm

stancufm May 12, 2017

I've started the run-sections project if you need more than just parsing arguments. With run-sections you can chose what part of you code do you want to run and much more. You can simply mark sections inside your script and run just that sections. If you are interested on this idea, please have a look on https://github.com/stancufm/run-sections . It's very easy to work with this function.

I've started the run-sections project if you need more than just parsing arguments. With run-sections you can chose what part of you code do you want to run and much more. You can simply mark sections inside your script and run just that sections. If you are interested on this idea, please have a look on https://github.com/stancufm/run-sections . It's very easy to work with this function.

@tchalvak

This comment has been minimized.

Show comment Hide comment
@tchalvak

tchalvak Jun 29, 2017

./simple_args_parsing.sh
./simple_args_parsing.sh: 13: ./simple_args_parsing.sh: Syntax error: "(" unexpected

Soo... not great.

./simple_args_parsing.sh
./simple_args_parsing.sh: 13: ./simple_args_parsing.sh: Syntax error: "(" unexpected

Soo... not great.

@gperreymond

This comment has been minimized.

Show comment Hide comment
@gperreymond

gperreymond Sep 28, 2017

Hotfix this

function usage()
{

With :

usage() {

gperreymond commented Sep 28, 2017

Hotfix this

function usage()
{

With :

usage() {
@bormansquirrel

This comment has been minimized.

Show comment Hide comment
@bormansquirrel

bormansquirrel Apr 9, 2018

Nice gist conception!
Just a small detail, add -e to echo commands in the help menu, so it will format special tab characters ...

bormansquirrel commented Apr 9, 2018

Nice gist conception!
Just a small detail, add -e to echo commands in the help menu, so it will format special tab characters ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment