Skip to content

Instantly share code, notes, and snippets.

@gocha
Last active July 17, 2018 02:57
Show Gist options
  • Save gocha/9b12fa0b7b5d18ae56e0452cec749e87 to your computer and use it in GitHub Desktop.
Save gocha/9b12fa0b7b5d18ae56e0452cec749e87 to your computer and use it in GitHub Desktop.
Powershell-flavored command line argument parser
#!/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