Create a gist now

Instantly share code, notes, and snippets.

Embed
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;

}

hypersoft commented 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;

}
@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"

perepechaev commented 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"

@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.

geoff-codes commented 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.

@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.

stancufm commented 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.

@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.

tchalvak commented Jun 29, 2017

./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 ...

@bestjejust

This comment has been minimized.

Show comment
Hide comment
@bestjejust

bestjejust May 31, 2018

echo "\t-h --help"

shouldn't it be echo -e? Otherwise it prints \t in my case.

Or better use printf?

bestjejust commented May 31, 2018

echo "\t-h --help"

shouldn't it be echo -e? Otherwise it prints \t in my case.

Or better use printf?

@elliotboney

This comment has been minimized.

Show comment
Hide comment
@elliotboney

elliotboney Jul 17, 2018

@geoff-codes thanks for the snippet! @hypersoft's solution was hella less readable

elliotboney commented Jul 17, 2018

@geoff-codes thanks for the snippet! @hypersoft's solution was hella less readable

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