mirror of
https://github.com/kvz/bash3boilerplate.git
synced 2025-06-01 22:30:42 +00:00
Merge pull request #3 from zbeekman/longargs
Enable long, GNU style options RE: issue-1
This commit is contained in:
commit
e90ad7421f
98
main.sh
98
main.sh
@ -24,16 +24,27 @@
|
|||||||
### Configuration
|
### Configuration
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
|
# Exit on error. Append ||true if you expect an error.
|
||||||
|
# `set` is safer than relying on a shebang like `#!/bin/bash -e` because that is neutralized
|
||||||
|
# when someone runs your script as `bash yourscript.sh`
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
|
||||||
|
# Bash will remember & return the highest exitcode in a chain of pipes.
|
||||||
|
# This way you can catch the error in case mysqldump fails in `mysqldump |gzip`
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
# Environment variables and their defaults
|
# Environment variables and their defaults
|
||||||
LOG_LEVEL="${LOG_LEVEL:-6}" # 7 = debug -> 0 = emergency
|
LOG_LEVEL="${LOG_LEVEL:-6}" # 7 = debug -> 0 = emergency
|
||||||
|
|
||||||
# Commandline options. This defines the usage page, and is used to parse cli
|
# Commandline options. This defines the usage page, and is used to parse cli
|
||||||
# opts & defaults from. The parsing is unforgiving so be precise in your syntax
|
# opts & defaults from. The parsing is unforgiving so be precise in your syntax
|
||||||
read -r -d '' usage <<-'EOF'
|
read -r -d '' usage <<-'EOF' || true # exits non-zero when EOF encountered
|
||||||
-f [arg] Filename to process. Required.
|
-f --file [arg] Filename to process. Required.
|
||||||
-t [arg] Location of tempfile. Default="/tmp/bar"
|
-t --temp [arg] Location of tempfile. Default="/tmp/bar"
|
||||||
-d Enables debug mode
|
-v Enable verbose mode, print script as it is executed
|
||||||
-h This page
|
-d --debug Enables debug mode
|
||||||
|
-h --help This page
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Set magic variables for current file and its directory.
|
# Set magic variables for current file and its directory.
|
||||||
@ -56,7 +67,7 @@ function _fmt () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local color_reset="\x1b[0m"
|
local color_reset="\x1b[0m"
|
||||||
if [[ "${TERM}" != "xterm"* ]] || [ -t 1 ]; then
|
if [[ "${TERM:-}" != "xterm"* ]] || [ -t 1 ]; then
|
||||||
# Don't use colors on pipes or non-recognized terminals
|
# Don't use colors on pipes or non-recognized terminals
|
||||||
color=""; color_reset=""
|
color=""; color_reset=""
|
||||||
fi
|
fi
|
||||||
@ -91,14 +102,26 @@ trap cleanup_before_exit EXIT
|
|||||||
|
|
||||||
# Translate usage string -> getopts arguments, and set $arg_<flag> defaults
|
# Translate usage string -> getopts arguments, and set $arg_<flag> defaults
|
||||||
while read line; do
|
while read line; do
|
||||||
opt="$(echo "${line}" |awk '{print $1}' |sed -e 's#^-##')"
|
# fetch single character version of option sting
|
||||||
|
opt="$(echo "${line}" |awk 'match($1,"^-.",a){print substr(a[0],2,1)}')"
|
||||||
|
|
||||||
|
# fetch long version if present
|
||||||
|
long_opt="$(echo "${line}" |awk 'match($2,"^--.*",a){print substr(a[0],3)}')"
|
||||||
|
# map long name back to short name
|
||||||
|
varname="short_opt_${long_opt}"
|
||||||
|
eval "${varname}=\"${opt}\""
|
||||||
|
|
||||||
|
# check if option takes an argument
|
||||||
|
varname="has_arg_${opt}"
|
||||||
if ! echo "${line}" |egrep '\[.*\]' >/dev/null 2>&1; then
|
if ! echo "${line}" |egrep '\[.*\]' >/dev/null 2>&1; then
|
||||||
init="0" # it's a flag. init with 0
|
init="0" # it's a flag. init with 0
|
||||||
|
eval "${varname}=0"
|
||||||
else
|
else
|
||||||
opt="${opt}:" # add : if opt has arg
|
opt="${opt}:" # add : if opt has arg
|
||||||
init="" # it has an arg. init with ""
|
init="" # it has an arg. init with ""
|
||||||
|
eval "${varname}=1"
|
||||||
fi
|
fi
|
||||||
opts="${opts}${opt}"
|
opts="${opts:-}${opt}"
|
||||||
|
|
||||||
varname="arg_${opt:0:1}"
|
varname="arg_${opt:0:1}"
|
||||||
if ! echo "${line}" |egrep '\. Default=' >/dev/null 2>&1; then
|
if ! echo "${line}" |egrep '\. Default=' >/dev/null 2>&1; then
|
||||||
@ -109,30 +132,44 @@ while read line; do
|
|||||||
fi
|
fi
|
||||||
done <<< "${usage}"
|
done <<< "${usage}"
|
||||||
|
|
||||||
|
# Allow long options like --this
|
||||||
|
opts="${opts}-:"
|
||||||
|
|
||||||
# Reset in case getopts has been used previously in the shell.
|
# Reset in case getopts has been used previously in the shell.
|
||||||
OPTIND=1
|
OPTIND=1
|
||||||
|
|
||||||
# Overwrite $arg_<flag> defaults with the actual CLI options
|
# Overwrite $arg_<flag> defaults with the actual CLI options
|
||||||
while getopts "${opts}" opt; do
|
while getopts "${opts}" opt; do
|
||||||
line="$(echo "${usage}" |grep "\-${opt}")"
|
|
||||||
|
|
||||||
|
|
||||||
[ "${opt}" = "?" ] && help "Invalid use of script: ${@} "
|
[ "${opt}" = "?" ] && help "Invalid use of script: ${@} "
|
||||||
varname="arg_${opt:0:1}"
|
|
||||||
default="${!varname}"
|
|
||||||
|
|
||||||
value="${OPTARG}"
|
if [ "${opt}" = "-" ]; then #OPTARG is long-option-name or long-option=value
|
||||||
if [ -z "${OPTARG}" ] && [ "${default}" = "0" ]; then
|
if [[ "${OPTARG}" =~ .*=.* ]]; then # --key=value format
|
||||||
value="1"
|
long=${OPTARG/=*/}
|
||||||
|
eval "opt=\"\${short_opt_${long}}\"" # Set opt to the short option corresponding to the long option
|
||||||
|
OPTARG=${OPTARG#*=}
|
||||||
|
else # --key value format
|
||||||
|
eval "opt=\"\${short_opt_${OPTARG}}\"" # Map long name to short version of option
|
||||||
|
eval "OPTARG=\"\${@:OPTIND:\${has_arg_${opt}}}\"" # Only assign OPTARG if option takes an argument
|
||||||
|
((OPTIND+=has_arg_${opt})) # shift over the argument if argument is expected
|
||||||
|
fi
|
||||||
|
# we have set opt/OPTARG to the short value and the argument as OPTARG if it exists
|
||||||
|
else
|
||||||
|
varname="arg_${opt:0:1}"
|
||||||
|
default="${!varname}"
|
||||||
|
|
||||||
|
value="${OPTARG:-}"
|
||||||
|
if [ -z "${OPTARG:-}" ] && [ "${default}" = "0" ]; then
|
||||||
|
value="1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
eval "${varname}=\"${value}\""
|
||||||
|
debug "cli arg ${varname} = ($default) -> ${!varname}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
eval "${varname}=\"${value}\""
|
|
||||||
debug "cli arg ${varname} = ($default) -> ${!varname}"
|
|
||||||
done
|
done
|
||||||
|
|
||||||
shift $((OPTIND-1))
|
shift $((OPTIND-1))
|
||||||
|
|
||||||
[ "$1" = "--" ] && shift
|
[ "${1:-}" = "--" ] && shift
|
||||||
|
|
||||||
|
|
||||||
### Switches (like -d for debugmode, -h for showing helppage)
|
### Switches (like -d for debugmode, -h for showing helppage)
|
||||||
@ -144,6 +181,11 @@ if [ "${arg_d}" = "1" ]; then
|
|||||||
LOG_LEVEL="7"
|
LOG_LEVEL="7"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# verbose mode
|
||||||
|
if [ "${arg_v}" = "1" ]; then
|
||||||
|
set -o verbose
|
||||||
|
fi
|
||||||
|
|
||||||
# help mode
|
# help mode
|
||||||
if [ "${arg_h}" = "1" ]; then
|
if [ "${arg_h}" = "1" ]; then
|
||||||
# Help exists with code 1
|
# Help exists with code 1
|
||||||
@ -154,24 +196,14 @@ fi
|
|||||||
### Validation (decide what's required for running your script and error out)
|
### Validation (decide what's required for running your script and error out)
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
[ -z "${arg_f}" ] && help "Setting a filename with -f is required"
|
[ -z "${arg_f:-}" ] && help "Setting a filename with -f or --file is required"
|
||||||
[ -z "${LOG_LEVEL}" ] && emergency "Cannot continue without LOG_LEVEL. "
|
[ -z "${LOG_LEVEL:-}" ] && emergency "Cannot continue without LOG_LEVEL. "
|
||||||
|
|
||||||
|
|
||||||
### Runtime
|
### Runtime
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
# Exit on error. Append ||true if you expect an error.
|
if [[ "${OSTYPE:-}" == "darwin"* ]]; then
|
||||||
# `set` is safer than relying on a shebang like `#!/bin/bash -e` because that is neutralized
|
|
||||||
# when someone runs your script as `bash yourscript.sh`
|
|
||||||
set -o errexit
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
# Bash will remember & return the highest exitcode in a chain of pipes.
|
|
||||||
# This way you can catch the error in case mysqldump fails in `mysqldump |gzip`
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
if [[ "${OSTYPE}" == "darwin"* ]]; then
|
|
||||||
info "You are on OSX"
|
info "You are on OSX"
|
||||||
else
|
else
|
||||||
info "You are on Linux"
|
info "You are on Linux"
|
||||||
|
@ -2,9 +2,10 @@ B3BP:STDIO_REPLACE_DATETIMES
|
|||||||
|
|
||||||
Help using {root}/main.sh
|
Help using {root}/main.sh
|
||||||
|
|
||||||
-f [arg] Filename to process. Required.
|
-f --file [arg] Filename to process. Required.
|
||||||
-t [arg] Location of tempfile. Default="{tmpdir}/bar"
|
-t --temp [arg] Location of tempfile. Default="{tmpdir}/bar"
|
||||||
-d Enables debug mode
|
-v Enable verbose mode, print script as it is executed
|
||||||
-h This page
|
-d --debug Enables debug mode
|
||||||
|
-h --help This page
|
||||||
|
|
||||||
{datetime} UTC [32m[ info][0m Cleaning up. Done
|
{datetime} UTC [32m[ info][0m Cleaning up. Done
|
||||||
|
Loading…
x
Reference in New Issue
Block a user