Giter Site home page Giter Site logo

ko1nksm / getoptions Goto Github PK

View Code? Open in Web Editor NEW
364.0 14.0 20.0 200 KB

An elegant option/argument parser for shell scripts (full support for bash and all POSIX shells)

License: Creative Commons Zero v1.0 Universal

Shell 96.66% Makefile 3.09% Dockerfile 0.25%
shell-scripts bash ksh zsh dash busybox argument parsing code-generator getopt

getoptions's Introduction

getoptions

Test codecov CodeFactor GitHub top language License

An elegant option parser for shell scripts (full support for all POSIX shells)

getoptions is a new option parser and generator written in POSIX-compliant shell script and released in august 2020. It is for those who want to support the POSIX / GNU style option syntax in your shell scripts. Most easy, simple, fast, small, extensible and portable. No more any loops and templates needed!

TL; DR

#!/bin/sh

VERSION="0.1"

parser_definition() {
  setup   REST help:usage -- "Usage: example.sh [options]... [arguments]..." ''
  msg -- 'Options:'
  flag    FLAG    -f --flag                 -- "takes no arguments"
  param   PARAM   -p --param                -- "takes one argument"
  option  OPTION  -o --option on:"default"  -- "takes one optional argument"
  disp    :usage  -h --help
  disp    VERSION    --version
}

eval "$(getoptions parser_definition) exit 1"

echo "FLAG: $FLAG, PARAM: $PARAM, OPTION: $OPTION"
printf '%s\n' "$@" # rest arguments

It generates a simple option parser code internally and parses the following arguments.

example.sh -f --flag -p VALUE --param VALUE -o --option -oVALUE --option=VALUE 1 2 3
$ example.sh --help

Usage: example.sh [options]... [arguments]...

Options:
  -f, --flag                  takes no arguments
  -p, --param PARAM           takes one argument
  -o, --option[=OPTION]       takes one optional argument
  -h, --help
      --version

Table of Contents

Features

  • Full support for all POSIX shells, no limitations, no bashisms
  • High portability, supports all platforms (Linux, macOS, Windows, etc) where works POSIX shells
  • Neither getopt nor getopts is used, and implemented with shell scripts only
  • Provides DSL-like shell script way to define parsers for flexibility and extensibility
  • No need for code generation from embedded special comments
  • Can be used as an option parser generator to run without getoptions
  • Support for POSIX [1] and GNU [2] [3] compliant option syntax
  • Support for long options
  • Support for subcommands
  • Support for abbreviation option
  • Support for automatic help generation
  • Support for options to call action function
  • Support for validation and custom error handler
  • Works fast with small overhead and small file size (5KB - 8KB) library
  • No global variables are used (except the special variables OPTARG and OPTIND)
  • Only a minimum of one (and a maximum of three) global functions are defined as a library
  • No worry about license, it's public domain (Creative Commons Zero v1.0 Universal)

getopt vs getopts vs getoptions

getopt getopts getoptions
Implementation external command shell builtin command shell script
Portability No Yes Yes
Short option beginning with - ✔️ ✔️ ✔️
Short option beginning with + ⚠ zsh, ksh, mksh only ✔️
Combining short options ✔️ ✔️ ✔️
Long option beginning with -- ⚠ GNU only ✔️
Long option beginning with - ⚠ GNU only ✔️ limited
Abbreviating long options ⚠ GNU only ✔️
Optional argument ⚠ GNU only ✔️
Option after arguments ⚠ GNU only ✔️
Stop option parsing with -- ✔️ ✔️ ✔️
Scanning modes ⚠ GNU only ✔️ + and enhancement
Subcommand ✔️
Validation by pattern matching ✔️
Custom validation ✔️
Custom error handler ✔️ ✔️ more flexible
Automatic help generation ✔️

Requirements

Almost no requirements.

  • Any POSIX shells
    • dash 0.5.4+, bash 2.03+, ksh 88+, mksh R28+, zsh 3.1.9+, yash 2.29+, busybox ash 1.1.3+, etc
  • Only cat is used for help display, but it can be removed

Installation

Download prebuild shell scripts from releases.

  • getoptions: Option parser
  • gengetoptions: Option parser generator
wget https://github.com/ko1nksm/getoptions/releases/latest/download/getoptions -O $HOME/bin/getoptions
chmod +x $HOME/bin/getoptions

# optional
wget https://github.com/ko1nksm/getoptions/releases/latest/download/gengetoptions -O $HOME/bin/gengetoptions
chmod +x $HOME/bin/gengetoptions

Or build and install it yourself.

git clone https://github.com/ko1nksm/getoptions.git
cd getoptions
make
make install PREFIX=$HOME

Homebrew / Linuxbrew

brew tap ko1nksm/getoptions
brew install getoptions

Usage

Support three ways of use. It is better to use it as a command at first, and then use it as a library or generator as needed.

command library generator
easy ★★★ ★★☆ ★☆☆
fast ★☆☆ ★★☆ ★★★

Use as a command

Use the getoptions command that you installed on your system. This assumes that you have the getoptions command installed, but it is the easiest to use and is suitable for personal scripts.

The execution speed is slightly slower than using it as a library. (Approx. 15ms overhead)

parser_definition() {
  setup REST help:usage -- "Usage: example.sh [options]... [arguments]..."
  ...
}

eval "$(getoptions parser_definition parse) exit 1"
parse "$@"
eval "set -- $REST"

The above code exit 1 is the recommended option. This allows you to exit if the getoptions command is not found.

If you omit the option parser name or use -, it will define the default option parser and parse arguments immediately.

parser_definition() {
  setup REST help:usage -- "Usage: example.sh [options]... [arguments]..."
  ...
}

eval "$(getoptions parser_definition) exit 1"

# The above means the same as the following code.
# eval "$(getoptions parser_definition getoptions_parse) exit 1"
# getoptions_parse "$@"
# eval "set -- $REST"

HINT: Are you wondering why the external command can call a shell function?

The external command getoptions will output the shell function getoptions. The external command getoptions will be hidden by the shell function getoptions that defined by eval, and the getoptions will be called again, so it can be call the shell function parser_definition.

Try running the following command to see what is output.

$ getoptions parser_definition parse

Use as a library

The getoptions command is not recommended for use in distribution scripts because it is not always installed on the system. This problem can be solved by including getoptions as a shell script library in your shell scripts.

To use getoptions as a library, you need to generate a library using the gengetoptions command. You can optionally adjust the indentation and other settings when generating the library.

$ gengetoptions library > getoptions.sh
. ./getoptions.sh # Or include it here

parser_definition() {
  setup REST help:usage -- "Usage: example.sh [options]... [arguments]..."
  ...
}

eval "$(getoptions parser_definition parse)"
parse "$@"
eval "set -- $REST"

NOTE for 1.x and 2.x users: The previous version guided you to use lib/*.sh. This is still available, but it is recommended to use gengetoptions library.

Use as a generator

If you do not want to include getoptions in your shell scripts, you can pre-generate an option parser. It also runs the fastest, so it suitable when you need a lot of options.

$ gengetoptions parser -f examples/parser_definition.sh parser_definition parse prog > parser.sh
. ./parser.sh # Or include it here

parse "$@"
eval "set -- $REST"

Embedding into a file

You can use gengetoptions embed to embed the generated code in a file, which makes maintenance easier.

If you want to write the parser definition in the same file as the shell script to execute, define it between @getoptions and @end. The code contained here will be executed during code generation.

The generated code will be embedded between the @gengetoptions and @end directives. The arguments of @gengetoptions are the same as the arguments of the gengetoptions command, which allows you to embed the library as well as the parser.

Example

example.sh

#!/bin/sh

set -eu

# @getoptions
parser_definition() {
  setup   REST help:usage -- "Usage: example.sh [options]... [arguments]..." ''
  msg -- 'Options:'
  flag    FLAG    -f --flag                 -- "takes no arguments"
  param   PARAM   -p --param                -- "takes one argument"
  option  OPTION  -o --option on:"default"  -- "takes one optional argument"
  disp    :usage  -h --help
  disp    VERSION    --version
}
# @end

# @gengetoptions parser -i parser_definition parse
#
#     INSERTED HERE
#
# @end

parse "$@"
eval "set -- $REST"

echo "FLAG: $FLAG, PARAM: $PARAM, OPTION: $OPTION"
printf '%s\n' "$@" # rest arguments
$ gengetoptions embed --overwrite example.sh

Benchmarks

Ubuntu (dash) Core i7 3.4 Ghz

[command]
Benchmark #1: ./example.sh --flag --param param --option=option a b c
  Time (mean ± σ):       8.6 ms ±   0.3 ms    [User: 6.3 ms, System: 0.6 ms]
  Range (min … max):     7.7 ms …  10.1 ms    300 runs

[library]
Benchmark #1: ./example.sh --flag --param param --option=option a b c
  Time (mean ± σ):       8.3 ms ±   0.4 ms    [User: 5.2 ms, System: 0.5 ms]
  Range (min … max):     7.4 ms …  10.5 ms    322 runs

[generator]
Benchmark #1: ./example.sh --flag --param param --option=option a b c
  Time (mean ± σ):       4.7 ms ±   0.3 ms    [User: 1.4 ms, System: 0.1 ms]
  Range (min … max):     4.4 ms …   6.5 ms    510 runs

macOS (bash), Core i5 2.4 GHz

[command]
Benchmark #1: ./example.sh --flag --param param --option=option a b c
  Time (mean ± σ):      37.6 ms ±   3.2 ms    [User: 29.2 ms, System: 7.4 ms]
  Range (min … max):    33.4 ms …  47.5 ms    66 runs

[library]
Benchmark #1: ./example.sh --flag --param param --option=option a b c
  Time (mean ± σ):      31.0 ms ±   3.7 ms    [User: 26.0 ms, System: 4.4 ms]
  Range (min … max):    26.4 ms …  43.8 ms    77 runs

[generator]
Benchmark #1: ./example.sh --flag --param param --option=option a b c
  Time (mean ± σ):       5.6 ms ±   2.1 ms    [User: 2.8 ms, System: 2.0 ms]
  Range (min … max):     3.9 ms …  15.1 ms    277 runs

How to see the option parser code

It is important to know what kind of code is being generated when the option parser is not working as expected.

If you want to see the option parser code, rewrite it as follows.

# eval "$(getoptions parser_definition parse) exit 1"

# Preload the getoptions library
# (can be omitted when using getoptions as a library)
eval "$(getoptions -)"

# Output of the option parser
getoptions parser_definition parse
exit

The option parsing code generated by getoptions is very simple.

Example option parser code
FLAG=''
PARAM=''
OPTION=''
REST=''
parse() {
  OPTIND=$(($#+1))
  while OPTARG= && [ $# -gt 0 ]; do
    case $1 in
      --?*=*) OPTARG=$1; shift
        eval 'set -- "${OPTARG%%\=*}" "${OPTARG#*\=}"' ${1+'"$@"'}
        ;;
      --no-*|--without-*) unset OPTARG ;;
      -[po]?*) OPTARG=$1; shift
        eval 'set -- "${OPTARG%"${OPTARG#??}"}" "${OPTARG#??}"' ${1+'"$@"'}
        ;;
      -[fh]?*) OPTARG=$1; shift
        eval 'set -- "${OPTARG%"${OPTARG#??}"}" -"${OPTARG#??}"' ${1+'"$@"'}
        OPTARG= ;;
    esac
    case $1 in
      '-f'|'--flag')
        [ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
        eval '[ ${OPTARG+x} ] &&:' && OPTARG='1' || OPTARG=''
        FLAG="$OPTARG"
        ;;
      '-p'|'--param')
        [ $# -le 1 ] && set "required" "$1" && break
        OPTARG=$2
        PARAM="$OPTARG"
        shift ;;
      '-o'|'--option')
        set -- "$1" "$@"
        [ ${OPTARG+x} ] && {
          case $1 in --no-*|--without-*) set "noarg" "${1%%\=*}"; break; esac
          [ "${OPTARG:-}" ] && { shift; OPTARG=$2; } || OPTARG='default'
        } || OPTARG=''
        OPTION="$OPTARG"
        shift ;;
      '-h'|'--help')
        usage
        exit 0 ;;
      '--version')
        echo "${VERSION}"
        exit 0 ;;
      --)
        shift
        while [ $# -gt 0 ]; do
          REST="${REST} \"\${$(($OPTIND-$#))}\""
          shift
        done
        break ;;
      [-]?*) set "unknown" "$1"; break ;;
      *)
        REST="${REST} \"\${$(($OPTIND-$#))}\""
    esac
    shift
  done
  [ $# -eq 0 ] && { OPTIND=1; unset OPTARG; return 0; }
  case $1 in
    unknown) set "Unrecognized option: $2" "$@" ;;
    noarg) set "Does not allow an argument: $2" "$@" ;;
    required) set "Requires an argument: $2" "$@" ;;
    pattern:*) set "Does not match the pattern (${1#*:}): $2" "$@" ;;
    notcmd) set "Not a command: $2" "$@" ;;
    *) set "Validation error ($1): $2" "$@"
  esac
  echo "$1" >&2
  exit 1
}
usage() {
cat<<'GETOPTIONSHERE'
Usage: example.sh [options]... [arguments]...

Options:
  -f, --flag                  takes no arguments
  -p, --param PARAM           takes one argument
  -o, --option[=OPTION]       takes one optional argument
  -h, --help
      --version
GETOPTIONSHERE
}
# Do not execute

Arguments containing spaces and quotes

The getoptions correctly handles arguments containing spaces and quotes without using arrays, which are not available in POSIX shells.

The magic is in the REST variable in the following code.

$ examples.sh --flag 1 --param value 2 -- 3

# examples.sh
...
eval "$(getoptions parser_definition parse "$0") exit 1"
parse "$@"
eval "set -- $REST"

echo "$REST" # => "${2}" "${5}" "${7}"
echo "$@" # => 1 2 3
...

Why reuse OPTARG and OPTIND for different purposes?

This is to avoid using valuable global variables. The POSIX shell does not have local variables. Instead of using long variable names to avoid conflicts, we reuse OPTARG and OPTIND. This code has been tested to work without any problem with all POSIX shells (e.g. ksh88, bash 2.03).

If you use getoptions instead of getopts for option parsing, OPTARG and OPTIND are not needed. In addition, you can also use getopts, since OPTARG and OPTIND will be correctly reset after use.

If you still don't like it, you can use the --optarg and --optind options of gengetoptions to change the variable name. In addition, since the license of getoptions is CC0, you can modify it to use it as you like.

About workarounds

The option parser code contains workarounds for some shell bugs. If you want to know what that code means, please refer to Workarounds.md.

References

For more information, see References.

Global functions

When the getoptions is used as an external command, three global functions, getoptions, getoptions_help, and getoptions_abbr, are defined in your shell script.

If you are using it as a library, only getoptions is required. The other functions are needed when the corresponding features are used.

Helper functions

Helper functions are (setup, flag, param, etc) used to define option parsers, and are defined only within the global functions described above.

Examples

Basic

basic.sh

This is an example of basic usage. It should be enough for your personal script.

Advanced

advanced.sh

Shell scripts distributed as utilities may require advanced features and validation.

Custom error handler

By defining the custom error handler, you can change the standard error messages, respond to additional error messages, and change the exit status.

Custom helper functions

By defining your own helper functions, you can easily define advanced options. For example, getoptions does not have a helper function to assign to the array, but it can be easily implemented by a custom helper function.

Subcommand

subcmd.sh

Complex programs are often implemented using subcommands. When using subcommands in getoptions, parse the arguments multiple times. (For example, parse up to the subcommand, and then parse after it. This design is useful for splitting shell scripts by each subcommand.

Prehook

prehook.sh

If you define a prehook function in the parser definition, it will be calledbefore helper functions is called. This allows you to process the arguments before calling the helper function.

This feature was originally designed to handle variable names with prefixes without complicating getoptions. Therefore, it may not be very flexible.

NOTE: The prehook function is not called in the help.

Extension

TODO: extension.sh

Recall that the parser definition function is just a shell script. You can extend the functionality by calling it from your function. For example, you could add a required attribute that means nonsense required options.

Practical example

getoptions was originally developed to improve the maintainability and testability for ShellSpec which has number of options. ShellSpec optparser is another good example of how to use getoptions.

NOTE: 2.x breaking changes

  • Calling getoptions_help is no longer needed (see help attribute)
  • Changed the default attribute of the option helper function to the on attribute
  • Improved the custom error handler and changed the arguments
  • Disable expansion variables in the help display

NOTE: 3.x breaking changes

  • Renamed lin/getoptions.sh to lin/getoptions_base.sh
  • Renamed getoptions-cli to gengetoptions
  • Moved library generation feature of getoptions to gengetoptions
  • Removed scanning mode = and #
  • Changed attribute off to no
  • Changed initial value @off to @no

For developers

How to test getoptions

Tests are executed using shellspec.

# Install shellspec (if not installed)
curl -fsSL https://git.io/shellspec | sh

# Run tests
shellspec

# Run tests with other shell
shellspec --shell bash

NOTE: Currently, only the option parser is being tested, and the CLI utilities is not being tested.

Changelog

CHANGELOG.md

License

Creative Commons Zero v1.0 Universal

All rights are relinquished and you can used as is or modified in your project. No credit is also required, but I would appreciate it if you could credit me as the original author.

getoptions's People

Contributors

cemkeylan avatar ko1nksm avatar robstoll avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

getoptions's Issues

Required param default error

First, this is a really great utility! Thanks so much for creating it.

I was wondering, do you have plans to support a default error for params that are required? Currently I have to do like this. Was wondering if those required param checks could be built in, and if you have plans for that.

eval "$(getoptions parser_definition parse "$0")" 
parse "$@"                         
               
[[ -z "${APPNAME-}" ]] && die "Missing required parameter: --appsvc-name"
[[ -z "${FILEPATH-}" ]] && die "Missing required parameter: --upload-filepath"

Missing information about how to use getoptions

Overall, it looks like a good tool, with many features, but learning how to use it is very time intensive. While there are some examples, there is hardly any explanation in the documentation.

I still have some questions unanswered, for example

  • What is the format of each of the following: "setup", "msg", "flag", "option", "param", and "disp"? Any others?
  • What is "mode"? How can it be used?
  • What is the difference between "parameter" and "option"?
  • How do I define the required parameters?

In addition, while getoptions looks useful, it is difficult to understand how it works from the code.

Brew tap ko1nksm/getoptions throws an Error

~
❯ brew tap ko1nksm/getoptions
Running `brew update --preinstall`...
[...]

==> Tapping ko1nksm/getoptions
Cloning into '/opt/homebrew/Library/Taps/ko1nksm/homebrew-getoptions'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 9 (delta 0), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), 4.36 KiB | 4.36 MiB/s, done.
Error: Invalid formula: /opt/homebrew/Library/Taps/ko1nksm/homebrew-getoptions/getoptions.rb
getoptions: Calling bottle :unneeded is disabled! There is no replacement.
Please report this issue to the ko1nksm/getoptions tap (not Homebrew/brew or Homebrew/core):
  /opt/homebrew/Library/Taps/ko1nksm/homebrew-getoptions/getoptions.rb:7

Error: Cannot tap ko1nksm/getoptions: invalid syntax in tap!

I forked your tap repo and removed the bottle :unneeded line and it works fine!

Mandatory/optional parameters

I'm often writing scripts that require some parameters to be provided when calling the script, while others are (and that seems to be the reasonable standard when using getoptions) completely (or conditionally – but that's to complicated here) optional. Even when using this super tool here, I am forced to check for the existence of my mandatory parameters after the parsing.

Could it be possible, to include this kind of simple mandatory check into this tool? (Maybe with a new annotation required, or a new type paramReq or so?)
If it could be automatically reflected by the generated options list would be a perfect bonus.

To demonstrate what I mean:

script.sh -a <valueA> [ -b <valueB> ]

This definition would not only require the existence of a value for <valueA> when calling with -a, but the existence of the parameter -a itself.

So the following calls would be correct:

script.sh -a ABCD
script.sh -a ABCD -b 1234

The following would be rejected by getoptions now (assuming that -a and -b configured as params):

script.sh -a

But this would be accepted (by now) also, despite the fact that I want to require the user to provide the -a flag:

script.sh
script.sh -c 1234

As a bonus this kind of "mandatory parameters" could be (optionally) visually be hinted by a small asterisk or some other little character, like so:

My script does the following …

OPTION DESCRIPTION
-a  * -- 'My mandatory param a'
-b    -- 'My normal/optional param b'
-c    -- 'and so on …'

Confusion about on: and no: in flag and option

I'm confused about on: and no: in the flag and option.

When I set this:

flag FLAG_D -d +d on:ON no:NO

./advanced -d returns FLAG_D: ON and ./advanced +d returns FLAG_D: NO.

In the reference, it states:

on:STRING - The positive value
no:STRING - The negative value

So I expected ./advanced -d to return the negative value. In the above case, it is NO.

When I use a plus sign in set command, it causes these options to be turned off. Is it the same way getoptions working?
If it is so, what do the positive and negative values stand?

What am I missing here?

Brew upgrade warning

When I run brew upgrade I get the following warning:

$ brew upgrade
Warning: Calling bottle :unneeded is deprecated! There is no replacement.
Please report this issue to the ko1nksm/getoptions tap (not Homebrew/brew or Homebrew/core):
  /opt/homebrew/Library/Taps/ko1nksm/homebrew-getoptions/getoptions.rb:7

Difference between param and option

What is the difference between param and option?

param - Define an option that takes an argument
option - Define an option that takes an optional argument

I can see that option has on and no:

on:STRING - The positive value
no:STRING - The negative value

It seems like a mixture of flag and option.
The option can be used as a flag and also you can add an argument.

Is this a correct interpretation?

Init attribute for options does not work

My understanding (possibly incorrect) based on the Reference document is that options (options with an optional argument) should be able to be:

  • set explicitly to some value passed on the actual command line (consistent with validation)
  • set to "on" value if the option is present in the commandline and no value is passed, -e.g. -n
  • set to the "no" value if the negated option is present in the commandline and no value is passed, e.g. +n
  • if the option is not passed on the commandline my expectation was that the init attribute would be the default

It seems that the last bullet item is not correct. The result is that options with optional values cannot have a default for when they are not present. I have tried setting a default as an explicit string

init:="missing value"

And I have tried setting it to one of the pre-defined expressions

init:@on

Note that the latter is still limiting because it would limit the default value to be either the on or the no value rather than a distinct value for the case when the option was not specified.

I believe the init option is not working for options (with optional values) currently. (It works fine for parameters)

Thanks again for this great tool. As you can see from the example, I prefer to use it with functions in library mode. In library mode I usually have strict mode enabled with "set -euo pipefail" enabled. But I have tested with strict mode disabled and the result is the same.

example.zip

Embedding with subcmd

Is there an example of using the embed options while there are multiple subcmds involved?

初期値のバックスラッシュが自動的にエスケープされる

getoptions を日頃より利用させてもらっております。開発者の皆様ありがとうございます。

以下のような ShellScript コードを作成し、 gengetoptions embed --overwrite を利用して、オプション解析のコードを追加した後実行すると、オプション -a のバックスラッシュが自動的にエスケープされるようです。

# @getoptions
parser_definition() {
  setup REST
  param a -a init:='\\'
}
# @end

# @gengetoptions parser -i parser_definition parse
# @end

parse "$@"
eval "set -- $REST"

printf '%s\n' "$a"

直接 -a を指定するとエスケープされないようです。

$ sh a
\
$ sh a -a '\\'
\\

この動作はバグでしょうか。それとも仕様でしょうか。

当方の動作環境は以下のようになります。

$ getoptions -v
v3.3.0
$ gengetoptions -v
v3.3.0
$ dpkg -l | grep dash
ii  dash                                   0.5.8-2.10                                       i386         POSIX-compliant shell

Fix SC2004

When I use getoptions, I always have to manually ignore SC2004 that ShellCheck points out.

In foo line 62:
          REST="${REST} \"\${$(($OPTIND-$#))}\""
                                ^-----^ SC2004 (style): $/${} is unnecessary on arithmetic variables.


In foo line 68:
        REST="${REST} \"\${$(($OPTIND-$#))}\""
                              ^-----^ SC2004 (style): $/${} is unnecessary on arithmetic variables.

For more information:
  https://www.shellcheck.net/wiki/SC2004 -- $/${} is unnecessary on arithmeti...
    59	      --)
    60	        shift
    61	        while [ $# -gt 0 ]; do
*   62	          REST="${REST} \"\${$(($OPTIND-$#))}\""
    63	          shift
    64	        done
    65	        break ;;
    66	      [-]?*) set "unknown" "$1"; break ;;
    67	      *)
*   68	        REST="${REST} \"\${$(($OPTIND-$#))}\""
    69	    esac
    70	    shift
    71	  done

Is it possible to fix this?

question/help - how to parse to display help (-h) message if there is zero option

subcmd.sh works all nice. I wonder if there is a way to let the command to display the help message if no option is provided.

... code from examples/subcmds.sh

eval "$(getoptions parser_definition parse "$0") exit 1"
parse "$@"
eval "set -- $REST"

if [ $# -gt 0 ]; then
	cmd=$1
	shift
	case $cmd in
		cmd1)
			eval "$(getoptions parser_definition_cmd1 parse "$0")"
			parse "$@"
			eval "set -- $REST"
			echo "FLAG_A: $FLAG_A"
			;;
		cmd2)
			eval "$(getoptions parser_definition_cmd2 parse "$0")"
			parse "$@"
			eval "set -- $REST"
			echo "FLAG_B: $FLAG_B"
			;;
		cmd3)
			eval "$(getoptions parser_definition_cmd3 parse "$0")"
			parse "$@"
			eval "set -- $REST"
			echo "FLAG_C: $FLAG_C"
			;;
		--) # no subcommand, arguments only
	esac
else
    echo "here!"
    ## How to let the command to display the help message here the same as --help option??
    eval "$(getoptions parser_definition parse "$0" "-h")"
fi
echo "GLOBAL: $GLOBAL"
i=0
while [ $# -gt 0 ] && i=$((i + 1)); do
	echo "$i: $1"
	shift
done

Init attribute not working for parameters

I see in both the Advanced example and in the Reference that parameters accept an init attribute. My understanding was that if the parameter is specified in the commandline, then a value must be supplied. However, if the parameter is not specified in the commandline, then presumably the init value will be applied as the default value of the parameter.

However, this does not seem to be working.
example.zip

[Question] Is there any way to ignore not defined option?

My use case is something like this:

I have an sh file that is used as a proxy for a binary. However I want to only parse "some" options while forwarding the others to the binary. Example: my.sh --proxy-option 1 --opt1 --opt2 - I want to only parse proxy-option while having the other options in "$@" (--opt1 --opt2). Is this possible?

Remove scanning mode = and #

This feature is currently not implemented correctly, and fixing it would increase the amount of code significantly, so it will remove it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.