Last active
July 17, 2018 02:57
-
-
Save gocha/9b12fa0b7b5d18ae56e0452cec749e87 to your computer and use it in GitHub Desktop.
Powershell-flavored command line argument parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Powershell-flavored command line argument parser. | |
# | |
# See ps_getopt_sample.sh for usage. | |
# <https://gist.github.com/gocha/8c74f9724bfb9c1e3a98b28bd5cceddc> | |
# | |
# License: Unlicensed | |
declare -A params | |
####################################### | |
# Output error message to STDERR | |
# Globals: | |
# None | |
# Arguments: | |
# Message | |
# Returns: | |
# None | |
####################################### | |
ps_getopt::error() { | |
echo "$(basename $0): $@" >&2 | |
} | |
####################################### | |
# Return whether the elements contain the specified value | |
# Globals: | |
# None | |
# Arguments: | |
# $1 value to compare the elements to | |
# ... the elements to examine | |
# Returns: | |
# 0 element is found | |
# 1 no such element is found | |
####################################### | |
ps_getopt::elementIn() { | |
local e match="$1" | |
shift | |
for e; do | |
[[ "$e" == "$match" ]] && return 0 | |
done | |
return 1 | |
} | |
####################################### | |
# Parse command line arguments | |
# Globals: | |
# params [out] the hash table to store the parameters | |
# Arguments: | |
# $1 [in] the global array symbol for the name of all acceptable parameters (ALL_PARAMS[@]) | |
# $2 [in] the global array symbol for the name of positional parameters (ORDINAL_PARAMS[@]) | |
# $3 [in] the global array symbol for the name of mandatory parameters (MANDATORY_PARAMS[@]) | |
# $4 [in] the global array symbol for the name of parameters which allows an empty string (EMPTY_ALLOWED_PARAMS[@]) | |
# $5 [in] the global array symbol for the name of switch (boolean) parameters (SWITCH_TYPE_PARAMS[@]) | |
# ... the command line arguments | |
# Returns: | |
# 0 upon success | |
# 1 on error | |
####################################### | |
ps_getopt() { | |
if [ $# -lt 5 ]; then | |
# 引数が少なすぎます。 | |
error "ps_getopt: Too few arguments." | |
return 1 | |
fi | |
local all_params=$1 | |
local ordinal_params=$2 | |
local mandatory_params=$3 | |
local empty_allowed_params=$4 | |
local switch_type_params=$5 | |
shift 5 | |
params=() | |
while [[ $# -ne 0 ]]; do | |
local arg=$1 | |
local param_name="" | |
if [[ "${arg:0:1}" = "-" ]]; then | |
param_name=${arg:1} | |
shift | |
else | |
# Find the first parameter that is not binded yet. | |
for name in ${!ordinal_params}; do | |
if [[ -z "${params[${name}]}" ]]; then | |
param_name=${name} | |
break | |
fi | |
done | |
if [[ -z "${param_name}" ]]; then | |
# 引数 '${arg}' を受け入れる位置指定パラメーターが見つかりません。 | |
ps_getopt::error "A positional parameter cannot be found that accepts argument '${arg}'." | |
return 1 | |
fi | |
fi | |
if ! ps_getopt::elementIn "${param_name}" "${!all_params}"; then | |
# パラメーター名 '${param_name}' に一致するパラメーターが見つかりません。 | |
ps_getopt::error "A parameter cannot be found that matches parameter name '${param_name}'." | |
return 1 | |
fi | |
if [[ ! -z "${params[${param_name}]}" ]]; then | |
# パラメーター '${param_name}' が複数回指定されているため、パラメーターをバインドできません。 | |
ps_getopt::error "Cannot bind parameter because parameter '${param_name}' is specified more than once." | |
return 1 | |
fi | |
if ps_getopt::elementIn "${param_name}" "${!switch_type_params}"; then | |
params[${param_name}]="true" | |
else | |
if ! ps_getopt::elementIn "${param_name}" "${!empty_allowed_params}"; then | |
if [[ -z "$1" ]]; then | |
# 引数が空の文字列であるため、パラメーター '${param_name}' にバインドできません。 | |
ps_getopt::error "Cannot bind argument to parameter '${param_name}' because it is null." | |
return 1 | |
fi | |
fi | |
params[${param_name}]=$1 | |
shift | |
fi | |
done | |
local first_prompt="true" | |
for name in "${!mandatory_params}"; do | |
if ! ps_getopt::elementIn "${name}" "${!params[@]}"; then | |
if [[ ! -z "${first_prompt}" ]]; then | |
# 次のパラメーターに値を指定してください: | |
echo "Supply values for the following parameters:" >&2 | |
unset first_prompt | |
fi | |
read -p "${name}: " 'params[${name}]' | |
if ! ps_getopt::elementIn "${name}" "${!empty_allowed_params}"; then | |
if [[ -z "${params[${name}]}" ]]; then | |
# 引数が空の文字列であるため、パラメーター '${name}' にバインドできません。 | |
ps_getopt::error "Cannot bind argument to parameter '${name}' because it is null." | |
return 1 | |
fi | |
fi | |
fi | |
done | |
[[ -z "${first_prompt}" ]] && echo | |
return 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment