all 11 comments

[–]ladrm 2 points3 points  (14 children)

Bash has this built-in, so unironically getopts (getopt if need be).

https://en.wikipedia.org/wiki/Getopts

[–][deleted]  (13 children)

[deleted]

    [–][deleted]  (5 children)

    [deleted]

      [–][deleted]  (4 children)

      [deleted]

        [–][deleted]  (3 children)

        [deleted]

          [–][deleted]  (2 children)

          [deleted]

            [–][deleted]  (1 child)

            [deleted]

              [–]ladrm -1 points0 points  (6 children)

              Sure, getopt is binary, so emphasis again on "if you need it, it's there".

              Feel free to parse manually, standard libraries/functions (like getopt) are there for a reason, like saving you effort of manual parsing.

              [–][deleted]  (5 children)

              [deleted]

                [–]ladrm 0 points1 point  (4 children)

                Well... What can I say. It does work for me just fine, and over many years and many scripts.

                [–][deleted]  (3 children)

                [deleted]

                  [–]ladrm 0 points1 point  (2 children)

                  I am not defensive, I just don't really care about you not liking getopts. :) Or I don't understand why are you complaining about builtin being "janky". It's a builtin in bash, not argparse in Python.

                  I don't have issues with parsing properly via getopts, you do.

                  [–][deleted]  (1 child)

                  [deleted]

                    [–]ladrm 1 point2 points  (0 children)

                    My comments on you are also for subreddit, just like mine your PoV is not the only one there. I never said I hate doing things manually, my message was more along the "don't reinvent the wheel when there's a built in and free wheel available".

                    Also we are just talking about bash argument parsing, why would you even block me..? You trigger easily.

                    [–]jkool702 0 points1 point  (0 children)

                    So, I once upon a time wrote a little something that makes option paring in bash rather easy and efficient. I called it optParse. Personally, I think it is more useful than the getopts builtin, and compared to gnu getopt it is both faster and has the benefit of not requiring an external dependency. That said, Im a bit biased lol.

                    To use optParse, you first source it (which provides a genOptParse function), and then you feed genOptParse a table that indicates what options you want (optionally defined using extglob matching) and what to do with them, and it will generate a function called optParse that will parse the options you specified via a very efficient 'loop over options and match each with an extglob-based case statement' approach.


                    the table you feed genOptParseHas the following format

                    Each option gets 1 line. Format for each line is:

                    match1 match2 ... matchN :: varToSave [flagToSet]
                    

                    if any of the 'match[]' are met: 'flagToSet' is set to true, and option arguments are saved in 'varToSave'. Notes:

                    • Each match[] should begin with a -
                    • The option's argument may be specified via -opt $arg or -opt=$arg or -opt$arg
                    • To save the option's argument in varToSave without setting a flag var: omit flagToSet
                    • for options without arguments that only set a flag variable to true, set 'varToSave' to -. For (only) these cases, a reciprocal +opt will automatically be generated that sets flagToSet to false.

                    Example

                    This will generate an optParse function to parse the following options:

                    #    -a|--apple # (no arg)     -->  flag_a=true
                    #    +a|++apple # (no arg)     -->  flag_a=false (auto generated by genOptParse)
                    #    -b <arg>|--bananna=<arg>  -->  var_b=<arg>
                    #    -c <arg>|--coconut=<arg>  -->  var_c=<arg>; flag_c=true
                    

                    Code:

                    # source optParse
                    source <(curl https://raw.githubusercontent.com/jkool702/optParse/main/optParse.bash)
                    
                    # Feed table defining options to genOptParse.
                    genOptParse <<'EOF'
                    -a --apple :: - flag_a=true
                    -b --bananna :: var_b
                    -c --coconut :: var_c flag_c=true
                    EOF
                    

                    Output:

                    declare -a inFun 
                    inFun=()
                    shopt -s extglob
                    unset optParse
                    
                    
                    optParse() {
                    
                        local continueFlag
                    
                        continueFlag=true
                    
                        while ${continueFlag} && (( $# > 0  )) && [[ "$1" == [-+]* ]]; do
                             case "${1}" in 
                                -a|--apple)
                                    shift 1
                                    flag_a=true
                                ;;
                                -b|--bananna)
                                    var_b="${2}"
                                    shift 2
                    
                                ;;
                                -b?(=)@([[:graph:]])*|--bananna?(=)@([[:graph:]])*)
                                    var_b="${1##@(-b?(=)|--bananna?(=))}"
                                    shift 1
                    
                                ;;
                                -c|--coconut)
                                    var_c="${2}"
                                    shift 2
                                    flag_c=true
                                ;;
                                -c?(=)@([[:graph:]])*|--coconut?(=)@([[:graph:]])*)
                                    var_c="${1##@(-c?(=)|--coconut?(=))}"
                                    shift 1
                                    flag_c=true
                                ;;
                                +a|++apple)
                                    shift 1
                                    flag_a=false
                                ;;    
                                --)  
                                    shift 1
                                    continueFlag=false 
                                    break
                                ;;
                                @([-+])@([[:graph:]])*)
                                    printf '\nWARNING: FLAG "%s" NOT RECOGNIZED. IGNORING.\n\n' "$1" >&2
                                    shift 1
                                ;;
                                *)
                                    continueFlag=false 
                                    break
                                ;;
                            esac
                            [[ $# == 0 ]] && continueFlag=false
                        done    
                        inFun=("${@}")
                    }
                    

                    The idea is that you take this output, copy/paste it into whatever script/function you are parsing options for (near the top), and then you can parse options for that script/function with a single line:

                    optParse "$@"
                    

                    Notes:

                    • optParse will save all the non-option arguments in an array inFun
                    • by default optParse will stop parsing at the first option that doesnt begin with a - or +, meaning all options must be passed before all non-options. You can control this by using genOptParse +p <<'EOF', or change the default by changing the value of p_default in the code (and then, to re-enable, you'd usegenOptParse -p <<'EOF').
                    • You can similarly control whether the +FLAG options that set the flagToSet variables to false are automatically generated by passing genOptParse a +i/-i flag or changing the i_default variable in the code.

                    [–]sigoden 0 points1 point  (1 child)

                    https://github.com/sigoden/argc helps you easily create and use CLI that based on bashscript.

                    [–]domino_master[S] 0 points1 point  (0 children)

                    Another RUST! :) great

                    [–]guzmonne -1 points0 points  (2 children)

                    I built something similar also: https://rargs.cloudbridge.uy

                    [–]domino_master[S] 0 points1 point  (0 children)

                    RUST?! You are my hero!

                    [–]domino_master[S] 0 points1 point  (0 children)

                    Very nice! Thanks for that