use 4 spaces for indent

This commit is contained in:
Nathaniel Landau
2021-08-09 12:23:55 -04:00
parent c430628f9d
commit 76c309161a
10 changed files with 1754 additions and 1733 deletions

View File

@@ -1,139 +1,140 @@
# Colors
if tput setaf 1 &>/dev/null; then
bold=$(tput bold)
white=$(tput setaf 7)
reset=$(tput sgr0)
purple=$(tput setaf 171)
red=$(tput setaf 1)
green=$(tput setaf 76)
tan=$(tput setaf 3)
yellow=$(tput setaf 3)
blue=$(tput setaf 38)
underline=$(tput sgr 0 1)
bold=$(tput bold)
white=$(tput setaf 7)
reset=$(tput sgr0)
purple=$(tput setaf 171)
red=$(tput setaf 1)
green=$(tput setaf 76)
tan=$(tput setaf 3)
yellow=$(tput setaf 3)
blue=$(tput setaf 38)
underline=$(tput sgr 0 1)
else
bold="\033[4;37m"
white="\033[0;37m"
reset="\033[0m"
purple="\033[0;35m"
red="\033[0;31m"
green="\033[1;32m"
tan="\033[0;33m"
yellow="\033[0;33m"
blue="\033[0;34m"
underline="\033[4;37m"
bold="\033[4;37m"
white="\033[0;37m"
reset="\033[0m"
purple="\033[0;35m"
red="\033[0;31m"
green="\033[1;32m"
tan="\033[0;33m"
yellow="\033[0;33m"
blue="\033[0;34m"
underline="\033[4;37m"
fi
_alert_() {
# DESC: Controls all printing of messages to log files and stdout.
# ARGS: $1 (required) - The type of alert to print
# (success, header, notice, dryrun, debug, warning, error,
# fatal, info, input)
# $2 (required) - The message to be printed to stdout and/or a log file
# $3 (optional) - Pass '${LINENO}' to print the line number where the _alert_ was triggered
# OUTS: None
# USAGE: [ALERTTYPE] "[MESSAGE]" "${LINENO}"
# NOTES: The colors of each alert type are set in this function
# For specified alert types, the funcstac will be printed
# DESC: Controls all printing of messages to log files and stdout.
# ARGS: $1 (required) - The type of alert to print
# (success, header, notice, dryrun, debug, warning, error,
# fatal, info, input)
# $2 (required) - The message to be printed to stdout and/or a log file
# $3 (optional) - Pass '${LINENO}' to print the line number where the _alert_ was triggered
# OUTS: None
# USAGE: [ALERTTYPE] "[MESSAGE]" "${LINENO}"
# NOTES: The colors of each alert type are set in this function
# For specified alert types, the funcstac will be printed
local function_name color
local alertType="${1}"
local message="${2}"
local line="${3:-}" # Optional line number
local function_name color
local alertType="${1}"
local message="${2}"
local line="${3:-}" # Optional line number
if [[ -n "${line}" && "${alertType}" =~ ^(fatal|error) && "${FUNCNAME[2]}" != "_trapCleanup_" ]]; then
message="${message} (line: ${line}) $(_functionStack_)"
elif [[ -n "${line}" && "${FUNCNAME[2]}" != "_trapCleanup_" ]]; then
message="${message} (line: ${line})"
elif [[ -z "${line}" && "${alertType}" =~ ^(fatal|error) && "${FUNCNAME[2]}" != "_trapCleanup_" ]]; then
message="${message} $(_functionStack_)"
fi
if [[ "${alertType}" =~ ^(error|fatal) ]]; then
color="${bold}${red}"
elif [ "${alertType}" = "warning" ]; then
color="${red}"
elif [ "${alertType}" = "success" ]; then
color="${green}"
elif [ "${alertType}" = "debug" ]; then
color="${purple}"
elif [ "${alertType}" = "header" ]; then
color="${bold}${tan}"
elif [[ "${alertType}" =~ ^(input|notice) ]]; then
color="${bold}"
elif [ "${alertType}" = "dryrun" ]; then
color="${blue}"
else
color=""
fi
_writeToScreen_() {
("${QUIET}") && return 0 # Print to console when script is not 'quiet'
[[ ${VERBOSE} == false && "${alertType}" =~ ^(debug|verbose) ]] && return 0
if ! [[ -t 1 ]]; then # Don't use colors on non-recognized terminals
color=""
reset=""
if [[ -n ${line} && ${alertType} =~ ^(fatal|error) && ${FUNCNAME[2]} != "_trapCleanup_" ]]; then
message="${message} (line: ${line}) $(_functionStack_)"
elif [[ -n ${line} && ${FUNCNAME[2]} != "_trapCleanup_" ]]; then
message="${message} (line: ${line})"
elif [[ -z ${line} && ${alertType} =~ ^(fatal|error) && ${FUNCNAME[2]} != "_trapCleanup_" ]]; then
message="${message} $(_functionStack_)"
fi
echo -e "$(date +"%r") ${color}$(printf "[%7s]" "${alertType}") ${message}${reset}"
}
_writeToScreen_
_writeToLog_() {
[[ "${alertType}" == "input" ]] && return 0
[[ "${LOGLEVEL}" =~ (off|OFF|Off) ]] && return 0
[ -z "${LOGFILE:-}" ] && fatal "\$LOGFILE must be set"
[ ! -d "$(dirname "${LOGFILE}")" ] && mkdir -p "$(dirname "${LOGFILE}")"
[[ ! -f "${LOGFILE}" ]] && touch "${LOGFILE}"
# Don't use colors in logs
if command -v gsed &>/dev/null; then
local cleanmessage="$(echo "${message}" | gsed -E 's/(\x1b)?\[(([0-9]{1,2})(;[0-9]{1,3}){0,2})?[mGK]//g')"
if [[ ${alertType} =~ ^(error|fatal) ]]; then
color="${bold}${red}"
elif [ "${alertType}" = "warning" ]; then
color="${red}"
elif [ "${alertType}" = "success" ]; then
color="${green}"
elif [ "${alertType}" = "debug" ]; then
color="${purple}"
elif [ "${alertType}" = "header" ]; then
color="${bold}${tan}"
elif [[ ${alertType} =~ ^(input|notice) ]]; then
color="${bold}"
elif [ "${alertType}" = "dryrun" ]; then
color="${blue}"
else
local cleanmessage="$(echo "${message}" | sed -E 's/(\x1b)?\[(([0-9]{1,2})(;[0-9]{1,3}){0,2})?[mGK]//g')"
color=""
fi
echo -e "$(date +"%b %d %R:%S") $(printf "[%7s]" "${alertType}") [$(/bin/hostname)] ${cleanmessage}" >>"${LOGFILE}"
}
# Write specified log level data to LOGFILE
case "${LOGLEVEL:-ERROR}" in
ALL|all|All)
_writeToLog_
;;
DEBUG|debug|Debug)
_writeToLog_
;;
INFO|info|Info)
if [[ "${alertType}" =~ ^(die|error|fatal|warning|info|notice|success) ]]; then
_writeToLog_
fi
;;
WARN|warn|Warn)
if [[ "${alertType}" =~ ^(die|error|fatal|warning) ]]; then
_writeToLog_
fi
;;
ERROR|error|Error)
if [[ "${alertType}" =~ ^(die|error|fatal) ]]; then
_writeToLog_
fi
;;
FATAL|fatal|Fatal)
if [[ "${alertType}" =~ ^(die|fatal) ]]; then
_writeToLog_
fi
;;
OFF|off)
return 0
;;
*)
if [[ "${alertType}" =~ ^(die|error|fatal) ]]; then
_writeToLog_
fi
;;
esac
_writeToScreen_() {
("${QUIET}") && return 0 # Print to console when script is not 'quiet'
[[ ${VERBOSE} == false && ${alertType} =~ ^(debug|verbose) ]] && return 0
if ! [[ -t 1 ]]; then # Don't use colors on non-recognized terminals
color=""
reset=""
fi
echo -e "$(date +"%r") ${color}$(printf "[%7s]" "${alertType}") ${message}${reset}"
}
_writeToScreen_
_writeToLog_() {
[[ ${alertType} == "input" ]] && return 0
[[ ${LOGLEVEL} =~ (off|OFF|Off) ]] && return 0
if [ -z "${LOGFILE:-}" ]; then
LOGFILE="$(pwd)/$(basename "$0").log"
fi
[ ! -d "$(dirname "${LOGFILE}")" ] && mkdir -p "$(dirname "${LOGFILE}")"
[[ ! -f ${LOGFILE} ]] && touch "${LOGFILE}"
# Don't use colors in logs
if command -v gsed &>/dev/null; then
local cleanmessage="$(echo "${message}" | gsed -E 's/(\x1b)?\[(([0-9]{1,2})(;[0-9]{1,3}){0,2})?[mGK]//g')"
else
local cleanmessage="$(echo "${message}" | sed -E 's/(\x1b)?\[(([0-9]{1,2})(;[0-9]{1,3}){0,2})?[mGK]//g')"
fi
echo -e "$(date +"%b %d %R:%S") $(printf "[%7s]" "${alertType}") [$(/bin/hostname)] ${cleanmessage}" >>"${LOGFILE}"
}
# Write specified log level data to logfile
case "${LOGLEVEL:-ERROR}" in
ALL | all | All)
_writeToLog_
;;
DEBUG | debug | Debug)
_writeToLog_
;;
INFO | info | Info)
if [[ ${alertType} =~ ^(die|error|fatal|warning|info|notice|success) ]]; then
_writeToLog_
fi
;;
WARN | warn | Warn)
if [[ ${alertType} =~ ^(die|error|fatal|warning) ]]; then
_writeToLog_
fi
;;
ERROR | error | Error)
if [[ ${alertType} =~ ^(die|error|fatal) ]]; then
_writeToLog_
fi
;;
FATAL | fatal | Fatal)
if [[ ${alertType} =~ ^(die|fatal) ]]; then
_writeToLog_
fi
;;
OFF | off)
return 0
;;
*)
if [[ ${alertType} =~ ^(die|error|fatal) ]]; then
_writeToLog_
fi
;;
esac
} # /_alert_
@@ -145,24 +146,30 @@ success() { _alert_ success "${1}" "${2:-}"; }
dryrun() { _alert_ dryrun "${1}" "${2:-}"; }
input() { _alert_ input "${1}" "${2:-}"; }
header() { _alert_ header "== ${1} ==" "${2:-}"; }
die() { _alert_ fatal "${1}" "${2:-}"; _safeExit_ "1" ; }
fatal() { _alert_ fatal "${1}" "${2:-}"; _safeExit_ "1" ; }
die() {
_alert_ fatal "${1}" "${2:-}"
_safeExit_ "1"
}
fatal() {
_alert_ fatal "${1}" "${2:-}"
_safeExit_ "1"
}
debug() { _alert_ debug "${1}" "${2:-}"; }
verbose() { _alert_ debug "${1}" "${2:-}"; }
_functionStack_() {
# DESC: Prints the function stack in use
# ARGS: None
# OUTS: Prints [function]:[file]:[line]
# NOTE: Does not print functions from the alert class
local _i
funcStackResponse=()
for ((_i = 1; _i < ${#BASH_SOURCE[@]}; _i++)); do
case "${FUNCNAME[$_i]}" in "_alert_" | "_trapCleanup_" | fatal | error | warning | verbose | debug | die) continue ;; esac
funcStackResponse+=("${FUNCNAME[$_i]}:$(basename ${BASH_SOURCE[$_i]}):${BASH_LINENO[$_i - 1]}")
done
printf "( "
printf %s "${funcStackResponse[0]}"
printf ' < %s' "${funcStackResponse[@]:1}"
printf ' )\n'
# DESC: Prints the function stack in use
# ARGS: None
# OUTS: Prints [function]:[file]:[line]
# NOTE: Does not print functions from the alert class
local _i
funcStackResponse=()
for ((_i = 1; _i < ${#BASH_SOURCE[@]}; _i++)); do
case "${FUNCNAME[$_i]}" in "_alert_" | "_trapCleanup_" | fatal | error | warning | notice | info | verbose | debug | dryrun | header | success | die) continue ;; esac
funcStackResponse+=("${FUNCNAME[$_i]}:$(basename ${BASH_SOURCE[$_i]}):${BASH_LINENO[_i - 1]}")
done
printf "( "
printf %s "${funcStackResponse[0]}"
printf ' < %s' "${funcStackResponse[@]:1}"
printf ' )\n'
}

View File

@@ -1,83 +1,82 @@
_inArray_() {
# DESC: Determine if a value is in an array
# ARGS: $1 (Required) - Value to search for
# $2 (Required) - Array written as ${ARRAY[@]}
# OUTS: true/false
# USAGE: if _inArray_ "VALUE" "${ARRAY[@]}"; then ...
# DESC: Determine if a value is in an array
# ARGS: $1 (Required) - Value to search for
# $2 (Required) - Array written as ${ARRAY[@]}
# OUTS: true/false
# USAGE: if _inArray_ "VALUE" "${ARRAY[@]}"; then ...
[[ $# -lt 2 ]] && fatal 'Missing required argument to _inArray_()!'
[[ $# -lt 2 ]] && fatal 'Missing required argument to _inArray_()!'
local value="$1"
shift
for arrayItem in "$@"; do
[[ "${arrayItem}" == "${value}" ]] && return 0
done
return 1
local value="$1"
shift
for arrayItem in "$@"; do
[[ ${arrayItem} == "${value}" ]] && return 0
done
return 1
}
_join_() {
# DESC: Joins items together with a user specified separator
# ARGS: $1 (Required) - Separator
# $@ (Required) - Items to be joined
# OUTS: Prints joined terms
# USAGE:
# _join_ , a "b c" d #a,b c,d
# _join_ / var local tmp #var/local/tmp
# _join_ , "${foo[@]}" #a,b,c
# NOTE: http://stackoverflow.com/questions/1527049/bash-join-elements-of-an-array
# DESC: Joins items together with a user specified separator
# ARGS: $1 (Required) - Separator
# $@ (Required) - Items to be joined
# OUTS: Prints joined terms
# USAGE:
# _join_ , a "b c" d #a,b c,d
# _join_ / var local tmp #var/local/tmp
# _join_ , "${foo[@]}" #a,b,c
# NOTE: http://stackoverflow.com/questions/1527049/bash-join-elements-of-an-array
[[ $# -lt 2 ]] && fatal 'Missing required argument to _join_()!'
[[ $# -lt 2 ]] && fatal 'Missing required argument to _join_()!'
local IFS="${1}"
shift
echo "${*}"
local IFS="${1}"
shift
echo "${*}"
}
_setdiff_() {
# DESC: Return items that exist in ARRAY1 that are do not exist in ARRAY2
# ARGS: $1 (Required) - Array 1 in format ${ARRAY[*]}
# $2 (Required) - Array 2 in format ${ARRAY[*]}
# OUTS: Prints unique terms
# USAGE: _setdiff_ "${array1[*]}" "${array2[*]}"
# NOTE: http://stackoverflow.com/a/1617303/142339
# DESC: Return items that exist in ARRAY1 that are do not exist in ARRAY2
# ARGS: $1 (Required) - Array 1 in format ${ARRAY[*]}
# $2 (Required) - Array 2 in format ${ARRAY[*]}
# OUTS: Prints unique terms
# USAGE: _setdiff_ "${array1[*]}" "${array2[*]}"
# NOTE: http://stackoverflow.com/a/1617303/142339
[[ $# -lt 2 ]] && fatal 'Missing required argument to _setdiff_()!'
[[ $# -lt 2 ]] && fatal 'Missing required argument to _setdiff_()!'
local debug skip a b
if [[ "$1" == 1 ]]; then
debug=1
shift
fi
if [[ "$1" ]]; then
local setdiffA setdiffB setdiffC
# shellcheck disable=SC2206
setdiffA=($1)
# shellcheck disable=SC2206
setdiffB=($2)
fi
setdiffC=()
for a in "${setdiffA[@]}"; do
skip=
for b in "${setdiffB[@]}"; do
[[ "$a" == "$b" ]] && skip=1 && break
local debug skip a b
if [[ $1 == 1 ]]; then
debug=1
shift
fi
if [[ "$1" ]]; then
local setdiffA setdiffB setdiffC
# shellcheck disable=SC2206
setdiffA=($1)
# shellcheck disable=SC2206
setdiffB=($2)
fi
setdiffC=()
for a in "${setdiffA[@]}"; do
skip=
for b in "${setdiffB[@]}"; do
[[ $a == "$b" ]] && skip=1 && break
done
[[ "$skip" ]] || setdiffC=("${setdiffC[@]}" "$a")
done
[[ "$skip" ]] || setdiffC=("${setdiffC[@]}" "$a")
done
[[ "$debug" ]] && for a in setdiffA setdiffB setdiffC; do
#shellcheck disable=SC1087
echo "$a ($(eval echo "\${#$a[*]}")) $(eval echo "\${$a[*]}")" 1>&2
done
[[ "$1" ]] && echo "${setdiffC[@]}"
[[ "$debug" ]] && for a in setdiffA setdiffB setdiffC; do
#shellcheck disable=SC1087
echo "$a ($(eval echo "\${#$a[*]}")) $(eval echo "\${$a[*]}")" 1>&2
done
[[ "$1" ]] && echo "${setdiffC[@]}"
}
_removeDupes_() {
# DESC: Removes duplicate array elements.
# ARGS: $1 (Required) - Input array
# OUTS: Prints de-duped elements to standard out
# USAGE: _removeDups_ "${array[@]}"
# NOTE: List order may not stay the same.
# https://github.com/dylanaraps/pure-bash-bible
# DESC: Removes duplicate array elements.
# ARGS: $1 (Required) - Input array
# OUTS: Prints de-duped elements to standard out
# USAGE: _removeDups_ "${array[@]}"
# NOTE: List order may not stay the same.
# https://github.com/dylanaraps/pure-bash-bible
declare -A tmp_array
for i in "$@"; do
@@ -88,11 +87,11 @@ _removeDupes_() {
}
_randomArrayElement_() {
# DESC: Selects a random item from an array
# ARGS: $1 (Required) - Input array
# OUTS: Prints result
# USAGE: _randomArrayElement_ "${array[@]}"
# NOTE: https://github.com/dylanaraps/pure-bash-bible
# DESC: Selects a random item from an array
# ARGS: $1 (Required) - Input array
# OUTS: Prints result
# USAGE: _randomArrayElement_ "${array[@]}"
# NOTE: https://github.com/dylanaraps/pure-bash-bible
# Usage: random_array_element "array"
local arr=("$@")
printf '%s\n' "${arr[RANDOM % $#]}"

View File

@@ -1,361 +1,360 @@
_execute_() {
# DESC: Executes commands with safety and logging options
# ARGS: $1 (Required) - The command to be executed. Quotation marks MUST be escaped.
# $2 (Optional) - String to display after command is executed
# OPTS: -v Always print debug output from the execute function
# -p Pass a failed command with 'return 0'. This effecively bypasses set -e.
# -e Bypass _alert_ functions and use 'echo RESULT'
# -s Use '_alert_ success' for successful output. (default is 'info')
# -q Do not print output (QUIET mode)
# OUTS: None
# USE : _execute_ "cp -R \"~/dir/somefile.txt\" \"someNewFile.txt\"" "Optional message"
# _execute_ -sv "mkdir \"some/dir\""
# NOTE:
# If $DRYRUN=true no commands are executed
# If $VERBOSE=true the command's native output is printed to
# stderr and stdin. This can be forced with `_execute_ -v`
# DESC: Executes commands with safety and logging options
# ARGS: $1 (Required) - The command to be executed. Quotation marks MUST be escaped.
# $2 (Optional) - String to display after command is executed
# OPTS: -v Always print debug output from the execute function
# -p Pass a failed command with 'return 0'. This effecively bypasses set -e.
# -e Bypass _alert_ functions and use 'echo RESULT'
# -s Use '_alert_ success' for successful output. (default is 'info')
# -q Do not print output (QUIET mode)
# OUTS: None
# USE : _execute_ "cp -R \"~/dir/somefile.txt\" \"someNewFile.txt\"" "Optional message"
# _execute_ -sv "mkdir \"some/dir\""
# NOTE:
# If $DRYRUN=true no commands are executed
# If $VERBOSE=true the command's native output is printed to
# stderr and stdin. This can be forced with `_execute_ -v`
local localVerbose=false
local passFailures=false
local echoResult=false
local successResult=false
local quietResult=false
local opt
local LOCAL_VERBOSE=false
local PASS_FAILURES=false
local ECHO_RESULT=false
local SUCCESS_RESULT=false
local QUIET_RESULT=false
local opt
local OPTIND=1
while getopts ":vVpPeEsSqQ" opt; do
case $opt in
v | V) localVerbose=true ;;
p | P) passFailures=true ;;
e | E) echoResult=true ;;
s | S) successResult=true ;;
q | Q) quietResult=true ;;
*)
{
error "Unrecognized option '$1' passed to _execute_. Exiting."
_safeExit_
}
;;
esac
done
shift $((OPTIND - 1))
local OPTIND=1
while getopts ":vVpPeEsSqQ" opt; do
case $opt in
v | V) LOCAL_VERBOSE=true ;;
p | P) PASS_FAILURES=true ;;
e | E) ECHO_RESULT=true ;;
s | S) SUCCESS_RESULT=true ;;
q | Q) QUIET_RESULT=true ;;
*)
{
error "Unrecognized option '$1' passed to _execute_. Exiting."
_safeExit_
}
;;
esac
done
shift $((OPTIND - 1))
local cmd="${1:?_execute_ needs a command}"
local message="${2:-$1}"
local CMD="${1:?_execute_ needs a command}"
local EXECUTE_MESSAGE="${2:-$1}"
local saveVerbose=$VERBOSE
if "${localVerbose}"; then
VERBOSE=true
fi
if "${DRYRUN}"; then
if "$quietResult"; then
VERBOSE=$saveVerbose
return 0
local SAVE_VERBOSE=${VERBOSE}
if "${LOCAL_VERBOSE}"; then
VERBOSE=true
fi
if [ -n "${2:-}" ]; then
dryrun "${1} (${2})" "$(caller)"
if "${DRYRUN}"; then
if "${QUIET_RESULT}"; then
VERBOSE=$SAVE_VERBOSE
return 0
fi
if [ -n "${2:-}" ]; then
dryrun "${1} (${2})" "$(caller)"
else
dryrun "${1}" "$(caller)"
fi
elif ${VERBOSE}; then
if eval "${CMD}"; then
if "${ECHO_RESULT}"; then
echo "${EXECUTE_MESSAGE}"
elif "${SUCCESS_RESULT}"; then
success "${EXECUTE_MESSAGE}"
else
info "${EXECUTE_MESSAGE}"
fi
VERBOSE=${SAVE_VERBOSE}
return 0
else
if "${ECHO_RESULT}"; then
echo "warning: ${EXECUTE_MESSAGE}"
else
warning "${EXECUTE_MESSAGE}"
fi
VERBOSE=${SAVE_VERBOSE}
"${PASS_FAILURES}" && return 0 || return 1
fi
else
dryrun "${1}" "$(caller)"
if eval "${CMD}" &>/dev/null; then
if "${QUIET_RESULT}"; then
VERBOSE=${SAVE_VERBOSE}
return 0
elif "${ECHO_RESULT}"; then
echo "${EXECUTE_MESSAGE}"
elif "${SUCCESS_RESULT}"; then
success "${EXECUTE_MESSAGE}"
else
info "${EXECUTE_MESSAGE}"
fi
VERBOSE=${SAVE_VERBOSE}
return 0
else
if "${ECHO_RESULT}"; then
echo "error: ${EXECUTE_MESSAGE}"
else
warning "${EXECUTE_MESSAGE}"
fi
VERBOSE=${SAVE_VERBOSE}
"${PASS_FAILURES}" && return 0 || return 1
fi
fi
elif ${VERBOSE}; then
if eval "${cmd}"; then
if "$echoResult"; then
echo "${message}"
elif "${successResult}"; then
success "${message}"
else
info "${message}"
fi
VERBOSE=$saveVerbose
return 0
else
if "$echoResult"; then
echo "warning: ${message}"
else
warning "${message}"
fi
VERBOSE=$saveVerbose
"${passFailures}" && return 0 || return 1
fi
else
if eval "${cmd}" &>/dev/null; then
if "$quietResult"; then
VERBOSE=$saveVerbose
return 0
elif "$echoResult"; then
echo "${message}"
elif "${successResult}"; then
success "${message}"
else
info "${message}"
fi
VERBOSE=$saveVerbose
return 0
else
if "$echoResult"; then
echo "error: ${message}"
else
warning "${message}"
fi
VERBOSE=$saveVerbose
"${passFailures}" && return 0 || return 1
fi
fi
}
_findBaseDir_() {
# DESC: Locates the real directory of the script being run. Similar to GNU readlink -n
# ARGS: None
# OUTS: Echo result to STDOUT
# USE : baseDir="$(_findBaseDir_)"
# cp "$(_findBaseDir_ "somefile.txt")" "other_file.txt"
# DESC: Locates the real directory of the script being run. Similar to GNU readlink -n
# ARGS: None
# OUTS: Echo result to STDOUT
# USE : baseDir="$(_findBaseDir_)"
# cp "$(_findBaseDir_ "somefile.txt")" "other_file.txt"
local SOURCE
local DIR
local SOURCE
local DIR
# Is file sourced?
[[ $_ != "$0" ]] \
&& SOURCE="${BASH_SOURCE[1]}" \
|| SOURCE="${BASH_SOURCE[0]}"
# Is file sourced?
[[ $_ != "$0" ]] \
&& SOURCE="${BASH_SOURCE[1]}" \
|| SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="${DIR}/${SOURCE}" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
echo "$(cd -P "$(dirname "${SOURCE}")" && pwd)"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="${DIR}/${SOURCE}" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
echo "$(cd -P "$(dirname "${SOURCE}")" && pwd)"
}
_checkBinary_() {
# DESC: Check if a binary exists in the search PATH
# ARGS: $1 (Required) - Name of the binary to check for existence
# OUTS: true/false
# USAGE: (_checkBinary_ ffmpeg ) && [SUCCESS] || [FAILURE]
if [[ $# -lt 1 ]]; then
error 'Missing required argument to _checkBinary_()!'
return 1
fi
# DESC: Check if a binary exists in the search PATH
# ARGS: $1 (Required) - Name of the binary to check for existence
# OUTS: true/false
# USAGE: (_checkBinary_ ffmpeg ) && [SUCCESS] || [FAILURE]
if [[ $# -lt 1 ]]; then
error 'Missing required argument to _checkBinary_()!'
return 1
fi
if ! command -v "$1" >/dev/null 2>&1; then
debug "Did not find dependency: '$1'"
return 1
fi
return 0
if ! command -v "$1" >/dev/null 2>&1; then
debug "Did not find dependency: '$1'"
return 1
fi
return 0
}
_haveFunction_() {
# DESC: Tests if a function exists.
# ARGS: $1 (Required) - Function name
# OUTS: true/false
local f
f="$1"
# DESC: Tests if a function exists.
# ARGS: $1 (Required) - Function name
# OUTS: true/false
local f
f="$1"
if declare -f "$f" &>/dev/null 2>&1; then
return 0
else
return 1
fi
if declare -f "${f}" &>/dev/null 2>&1; then
return 0
else
return 1
fi
}
_pauseScript_() {
# DESC: Pause a script at any point and continue after user input
# ARGS: $1 (Optional) - String for customized message
# OUTS: None
# DESC: Pause a script at any point and continue after user input
# ARGS: $1 (Optional) - String for customized message
# OUTS: None
local pauseMessage
pauseMessage="${1:-Paused}. Ready to continue?"
local pauseMessage
pauseMessage="${1:-Paused}. Ready to continue?"
if _seekConfirmation_ "${pauseMessage}"; then
info "Continuing..."
else
notice "Exiting Script"
_safeExit_
fi
if _seekConfirmation_ "${pauseMessage}"; then
info "Continuing..."
else
notice "Exiting Script"
_safeExit_
fi
}
_progressBar_() {
# DESC: Prints a progress bar within a for/while loop
# ARGS: $1 (Required) - The total number of items counted
# $2 (Optional) - The optional title of the progress bar
# OUTS: None
# USAGE:
# for number in $(seq 0 100); do
# sleep 1
# _progressBar_ "100" "Counting numbers"
# done
# DESC: Prints a progress bar within a for/while loop
# ARGS: $1 (Required) - The total number of items counted
# $2 (Optional) - The optional title of the progress bar
# OUTS: None
# USAGE:
# for number in $(seq 0 100); do
# sleep 1
# _progressBar_ "100" "Counting numbers"
# done
($QUIET) && return
($VERBOSE) && return
[ ! -t 1 ] && return # Do nothing if the output is not a terminal
[ $1 == 1 ] && return # Do nothing with a single element
($QUIET) && return
($VERBOSE) && return
[ ! -t 1 ] && return # Do nothing if the output is not a terminal
[ $1 == 1 ] && return # Do nothing with a single element
local width bar_char perc num bar progressBarLine barTitle n
local width bar_char perc num bar progressBarLine barTitle n
n="${1:?_progressBar_ needs input}"
((n = n - 1))
barTitle="${2:-Running Process}"
width=30
bar_char="#"
n="${1:?_progressBar_ needs input}"
((n = n - 1))
barTitle="${2:-Running Process}"
width=30
bar_char="#"
# Reset the count
[ -z "${progressBarProgress}" ] && progressBarProgress=0
tput civis # Hide the cursor
trap 'tput cnorm; exit 1' SIGINT
# Reset the count
[ -z "${progressBarProgress}" ] && progressBarProgress=0
tput civis # Hide the cursor
trap 'tput cnorm; exit 1' SIGINT
if [ ! "${progressBarProgress}" -eq $n ]; then
#echo "progressBarProgress: $progressBarProgress"
# Compute the percentage.
perc=$((progressBarProgress * 100 / $1))
# Compute the number of blocks to represent the percentage.
num=$((progressBarProgress * width / $1))
# Create the progress bar string.
bar=""
if [ ${num} -gt 0 ]; then
bar=$(printf "%0.s${bar_char}" $(seq 1 ${num}))
if [ ! "${progressBarProgress}" -eq $n ]; then
#echo "progressBarProgress: $progressBarProgress"
# Compute the percentage.
perc=$((progressBarProgress * 100 / $1))
# Compute the number of blocks to represent the percentage.
num=$((progressBarProgress * width / $1))
# Create the progress bar string.
bar=""
if [ ${num} -gt 0 ]; then
bar=$(printf "%0.s${bar_char}" $(seq 1 ${num}))
fi
# Print the progress bar.
progressBarLine=$(printf "%s [%-${width}s] (%d%%)" " ${barTitle}" "${bar}" "${perc}")
echo -ne "${progressBarLine}\r"
progressBarProgress=$((progressBarProgress + 1))
else
# Clear the progress bar when complete
# echo -ne "\033[0K\r"
tput el # Clear the line
unset progressBarProgress
fi
# Print the progress bar.
progressBarLine=$(printf "%s [%-${width}s] (%d%%)" " ${barTitle}" "${bar}" "${perc}")
echo -ne "${progressBarLine}\r"
progressBarProgress=$((progressBarProgress + 1))
else
# Clear the progress bar when complete
# echo -ne "\033[0K\r"
tput el # Clear the line
unset progressBarProgress
fi
tput cnorm
tput cnorm
}
_rootAvailable_() {
# DESC: Validate we have superuser access as root (via sudo if requested)
# ARGS: $1 (optional): Set to any value to not attempt root access via sudo
# OUTS: None
# NOTE: https://github.com/ralish/bash-script-template
# DESC: Validate we have superuser access as root (via sudo if requested)
# ARGS: $1 (optional): Set to any value to not attempt root access via sudo
# OUTS: None
# NOTE: https://github.com/ralish/bash-script-template
local superuser
if [[ ${EUID} -eq 0 ]]; then
superuser=true
elif [[ -z ${1:-} ]]; then
if command -v sudo &>/dev/null; then
debug 'Sudo: Updating cached credentials ...'
if ! sudo -v; then
warning "Sudo: Couldn't acquire credentials ..."
else
local test_euid
test_euid="$(sudo -H -- "$BASH" -c 'printf "%s" "$EUID"')"
if [[ ${test_euid} -eq 0 ]]; then
superuser=true
local superuser
if [[ ${EUID} -eq 0 ]]; then
superuser=true
elif [[ -z ${1:-} ]]; then
if command -v sudo &>/dev/null; then
debug 'Sudo: Updating cached credentials ...'
if ! sudo -v; then
warning "Sudo: Couldn't acquire credentials ..."
else
local test_euid
test_euid="$(sudo -H -- "$BASH" -c 'printf "%s" "$EUID"')"
if [[ ${test_euid} -eq 0 ]]; then
superuser=true
fi
fi
fi
fi
fi
fi
if [[ -z ${superuser:-} ]]; then
notice 'Unable to acquire superuser credentials.'
return 1
fi
if [[ -z ${superuser:-} ]]; then
notice 'Unable to acquire superuser credentials.'
return 1
fi
info 'Successfully acquired superuser credentials.'
return 0
info 'Successfully acquired superuser credentials.'
return 0
}
_runAsRoot_() {
# DESC: Run the requested command as root (via sudo if requested)
# ARGS: $1 (optional): Set to zero to not attempt execution via sudo
# $@ (required): Passed through for execution as root user
# OUTS: None
# NOTE: https://github.com/ralish/bash-script-template
# DESC: Run the requested command as root (via sudo if requested)
# ARGS: $1 (optional): Set to zero to not attempt execution via sudo
# $@ (required): Passed through for execution as root user
# OUTS: None
# NOTE: https://github.com/ralish/bash-script-template
if [[ $# -eq 0 ]]; then
fatal 'Missing required argument to _runAsRoot_()!'
fi
if [[ $# -eq 0 ]]; then
fatal 'Missing required argument to _runAsRoot_()!'
fi
if [[ ${1:-} =~ ^0$ ]]; then
local skip_sudo=true
shift
fi
if [[ ${1:-} =~ ^0$ ]]; then
local skip_sudo=true
shift
fi
if [[ ${EUID} -eq 0 ]]; then
"$@"
elif [[ -z ${skip_sudo:-} ]]; then
sudo -H -- "$@"
else
fatal "Unable to run requested command as root: $*"
fi
if [[ ${EUID} -eq 0 ]]; then
"$@"
elif [[ -z ${skip_sudo:-} ]]; then
sudo -H -- "$@"
else
fatal "Unable to run requested command as root: $*"
fi
}
_seekConfirmation_() {
# DESC: Seek user input for yes/no question
# ARGS: $1 (Optional) - Question being asked
# OUTS: true/false
# USAGE: _seekConfirmation_ "Do something?" && echo "okay" || echo "not okay"
# OR
# if _seekConfirmation_ "Answer this question"; then
# something
# fi
# DESC: Seek user input for yes/no question
# ARGS: $1 (Optional) - Question being asked
# OUTS: true/false
# USAGE: _seekConfirmation_ "Do something?" && echo "okay" || echo "not okay"
# OR
# if _seekConfirmation_ "Answer this question"; then
# something
# fi
input "${1:-}"
if "${FORCE}"; then
debug "Forcing confirmation with '--force' flag set"
echo -e ""
return 0
else
while true; do
read -r -p " (y/n) " yn
case $yn in
[Yy]*) return 0 ;;
[Nn]*) return 1 ;;
*) input "Please answer yes or no." ;;
esac
done
fi
input "${1:-}"
if "${FORCE}"; then
debug "Forcing confirmation with '--force' flag set"
echo -e ""
return 0
else
while true; do
read -r -p " (y/n) " yn
case $yn in
[Yy]*) return 0 ;;
[Nn]*) return 1 ;;
*) input "Please answer yes or no." ;;
esac
done
fi
}
_setPATH_() {
# DESC: Add directories to $PATH so script can find executables
# ARGS: $@ - One or more paths
# OUTS: $PATH
# USAGE: _setPATH_ "/usr/local/bin" "${HOME}/bin" "$(npm bin)"
local NEWPATH NEWPATHS USERPATH
# DESC: Add directories to $PATH so script can find executables
# ARGS: $@ - One or more paths
# OUTS: $PATH
# USAGE: _setPATH_ "/usr/local/bin" "${HOME}/bin" "$(npm bin)"
local NEWPATH NEWPATHS USERPATH
for USERPATH in "$@"; do
NEWPATHS+=("$USERPATH")
done
for USERPATH in "$@"; do
NEWPATHS+=("$USERPATH")
done
for NEWPATH in "${NEWPATHS[@]}"; do
if ! echo "$PATH" | grep -Eq "(^|:)${NEWPATH}($|:)"; then
PATH="${NEWPATH}:${PATH}"
debug "Added '${tan}${NEWPATH}${purple}' to PATH"
fi
done
for NEWPATH in "${NEWPATHS[@]}"; do
if ! echo "$PATH" | grep -Eq "(^|:)${NEWPATH}($|:)"; then
PATH="${NEWPATH}:${PATH}"
debug "Added '${tan}${NEWPATH}${purple}' to PATH"
fi
done
}
_safeExit_() {
# DESC: Cleanup and exit from a script
# ARGS: $1 (optional) - Exit code (defaults to 0)
# OUTS: None
# DESC: Cleanup and exit from a script
# ARGS: $1 (optional) - Exit code (defaults to 0)
# OUTS: None
if [[ -d "${script_lock:-}" ]]; then
if command rm -rf "${script_lock}"; then
debug "Removing script lock"
else
warning "Script lock could not be removed. Try manually deleting ${tan}'${lock_dir}'${red}"
if [[ -d ${SCRIPT_LOCK:-} ]]; then
if command rm -rf "${SCRIPT_LOCK}"; then
debug "Removing script lock"
else
warning "Script lock could not be removed. Try manually deleting ${tan}'${LOCK_DIR}'${red}"
fi
fi
fi
if [[ -n "${tmpDir:-}" && -d "${tmpDir:-}" ]]; then
if [[ ${1:-} == 1 && -n "$(ls "${tmpDir}")" ]]; then
command rm -r "${tmpDir}"
else
command rm -r "${tmpDir}"
debug "Removing temp directory"
if [[ -n ${TMP_DIR:-} && -d ${TMP_DIR:-} ]]; then
if [[ ${1:-} == 1 && -n "$(ls "${TMP_DIR}")" ]]; then
command rm -r "${TMP_DIR}"
else
command rm -r "${TMP_DIR}"
debug "Removing temp directory"
fi
fi
fi
trap - INT TERM EXIT
exit ${1:-0}
trap - INT TERM EXIT
exit ${1:-0}
}

View File

@@ -1,34 +1,34 @@
_makeCSV_() {
# Creates a new CSV file if one does not already exist
# Takes passed arguments and writes them as a header line to the CSV
# Usage '_makeCSV_ column1 column2 column3'
# Creates a new CSV file if one does not already exist
# Takes passed arguments and writes them as a header line to the CSV
# Usage '_makeCSV_ column1 column2 column3'
# Set the location and name of the CSV File
if [ -z "${csvLocation}" ]; then
csvLocation="${HOME}/Desktop"
fi
if [ -z "${csvName}" ]; then
csvName="$(LC_ALL=C date +%Y-%m-%d)-${FUNCNAME[1]}.csv"
fi
csvFile="${csvLocation}/${csvName}"
# Overwrite existing file? If not overwritten, new content is added
# to the bottom of the existing file
if [ -f "${csvFile}" ]; then
if _seekConfirmation_ "${csvFile} already exists. Overwrite?"; then
rm "${csvFile}"
# Set the location and name of the CSV File
if [ -z "${csvLocation}" ]; then
csvLocation="${HOME}/Desktop"
fi
fi
_writeCSV_ "$@"
if [ -z "${csvName}" ]; then
csvName="$(LC_ALL=C date +%Y-%m-%d)-${FUNCNAME[1]}.csv"
fi
csvFile="${csvLocation}/${csvName}"
# Overwrite existing file? If not overwritten, new content is added
# to the bottom of the existing file
if [ -f "${csvFile}" ]; then
if _seekConfirmation_ "${csvFile} already exists. Overwrite?"; then
rm "${csvFile}"
fi
fi
_writeCSV_ "$@"
}
_writeCSV_() {
# Takes passed arguments and writes them as a comma separated line
# Usage '_writeCSV_ column1 column2 column3'
# Takes passed arguments and writes them as a comma separated line
# Usage '_writeCSV_ column1 column2 column3'
local csvInput=("$@")
saveIFS=$IFS
IFS=','
echo "${csvInput[*]}" >>"${csvFile}"
IFS=${saveIFS}
local csvInput=("$@")
saveIFS=$IFS
IFS=','
echo "${csvInput[*]}" >>"${csvFile}"
IFS=${saveIFS}
}

View File

@@ -1,381 +1,392 @@
_monthToNumber_() {
# DESC: Convert a month name to a number
# ARGS: None
# OUTS: Prints the number of the month to stdout
# USAGE: _monthToNumber_ "January"
# DESC: Convert a month name to a number
# ARGS: None
# OUTS: Prints the number of the month to stdout
# USAGE: _monthToNumber_ "January"
local mon="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
case "$mon" in
january|jan|ja) echo 1 ;;
february|feb|fe) echo 2 ;;
march|mar|ma) echo 3 ;;
april|apr|ap) echo 4 ;;
may) echo 5 ;;
june|jun|ju) echo 6 ;;
july|jul) echo 7 ;;
august|aug|au) echo 8 ;;
september|sep|se) echo 9 ;;
october|oct) echo 10 ;;
november|nov|no) echo 11 ;;
december|dec|de) echo 12 ;;
*)
warning "month_monthToNumber_: Bad monthname: $1"
return 1 ;;
esac
local mon="$(echo "$1" | tr '[:upper:]' '[:lower:]')"
case "$mon" in
january | jan | ja) echo 1 ;;
february | feb | fe) echo 2 ;;
march | mar | ma) echo 3 ;;
april | apr | ap) echo 4 ;;
may) echo 5 ;;
june | jun | ju) echo 6 ;;
july | jul) echo 7 ;;
august | aug | au) echo 8 ;;
september | sep | se) echo 9 ;;
october | oct) echo 10 ;;
november | nov | no) echo 11 ;;
december | dec | de) echo 12 ;;
*)
warning "month_monthToNumber_: Bad monthname: $1"
return 1
;;
esac
}
_numberToMonth_() {
# DESC: Convert a month number to its name
# ARGS: None
# OUTS: Prints the name of the month to stdout
# USAGE: _numberToMonth_ 1
# DESC: Convert a month number to its name
# ARGS: None
# OUTS: Prints the name of the month to stdout
# USAGE: _numberToMonth_ 1
local mon="$1"
case "$mon" in
1|01) echo January ;;
2|02) echo February ;;
3|03) echo March ;;
4|04) echo April ;;
5|05) echo May ;;
6|06) echo June ;;
7|07) echo July ;;
8|08) echo August ;;
9|09) echo September ;;
10) echo October ;;
11) echo November ;;
12) echo December ;;
*)
warning "_numberToMonth_: Bad month number: $1"
return 1 ;;
esac
local mon="$1"
case "$mon" in
1 | 01) echo January ;;
2 | 02) echo February ;;
3 | 03) echo March ;;
4 | 04) echo April ;;
5 | 05) echo May ;;
6 | 06) echo June ;;
7 | 07) echo July ;;
8 | 08) echo August ;;
9 | 09) echo September ;;
10) echo October ;;
11) echo November ;;
12) echo December ;;
*)
warning "_numberToMonth_: Bad month number: $1"
return 1
;;
esac
}
_parseDate_() {
# DESC: Takes a string as input and attempts to find a date within it
# to parse into component parts (day, month, year)
# ARGS: $1 (required) - A string
# OUTS: Returns error if no date found
# $_parseDate_found - The date found in the string
# $_parseDate_year - The year
# $_parseDate_month - The number month
# $_parseDate_monthName - The name of the month
# $_parseDate_day - The day
# $_parseDate_hour - The hour (if avail)
# $_parseDate_minute - The minute (if avail)
# USAGE: if _parseDate_ "[STRING]"; then ...
# NOTE: This function only recognizes dates from the year 2000 to 2029
# NOTE: Will recognize dates in the following formats separated by '-_ ./'
# * YYYY-MM-DD * Month DD, YYYY * DD Month, YYYY
# * Month, YYYY * Month, DD YY * MM-DD-YYYY
# * MMDDYYYY * YYYYMMDD * DDMMYYYY
# * YYYYMMDDHHMM * YYYYMMDDHH * DD-MM-YYYY
# * DD MM YY * MM DD YY
# TODO: Impelemt the following date formats
# * MMDDYY * YYMMDD * mon-DD-YY
# DESC: Takes a string as input and attempts to find a date within it
# to parse into component parts (day, month, year)
# ARGS: $1 (required) - A string
# OUTS: Returns error if no date found
# $_parseDate_found - The date found in the string
# $_parseDate_year - The year
# $_parseDate_month - The number month
# $_parseDate_monthName - The name of the month
# $_parseDate_day - The day
# $_parseDate_hour - The hour (if avail)
# $_parseDate_minute - The minute (if avail)
# USAGE: if _parseDate_ "[STRING]"; then ...
# NOTE: This function only recognizes dates from the year 2000 to 2029
# NOTE: Will recognize dates in the following formats separated by '-_ ./'
# * YYYY-MM-DD * Month DD, YYYY * DD Month, YYYY
# * Month, YYYY * Month, DD YY * MM-DD-YYYY
# * MMDDYYYY * YYYYMMDD * DDMMYYYY
# * YYYYMMDDHHMM * YYYYMMDDHH * DD-MM-YYYY
# * DD MM YY * MM DD YY
# TODO: Impelemt the following date formats
# * MMDDYY * YYMMDD * mon-DD-YY
[[ $# -eq 0 ]] && {
error 'Missing required argument to _parseDate_()!'
return 1
}
local date="${1:-$(date +%F)}"
_parseDate_found="" _parseDate_year="" _parseDate_month="" _parseDate_monthName=""
_parseDate_day="" _parseDate_hour="" _parseDate_minute=""
shopt -s nocasematch #Use case-insensitive regex
debug "_parseDate_() input ${tan}$date${purple}"
# YYYY MM DD or YYYY-MM-DD
pat="(.*[^0-9]|^)((20[0-2][0-9])[-\.\/_ ]+([ 0-9]{1,2})[-\.\/_ ]+([ 0-9]{1,2}))([^0-9].*|$)"
if [[ "${date}" =~ $pat ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year=$(( 10#${BASH_REMATCH[3]} ))
_parseDate_month=$(( 10#${BASH_REMATCH[4]} ))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[5]} ))
debug "regex match: ${tan}YYYY-MM-DD${purple}"
# Month DD, YYYY
elif [[ "${date}" =~ ((january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec)[-\./_ ]+([0-9]{1,2})(nd|rd|th|st)?,?[-\./_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[1]:-}"
_parseDate_month=$(_monthToNumber_ ${BASH_REMATCH[2]:-})
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month:-}")"
_parseDate_day=$(( 10#${BASH_REMATCH[3]:-} ))
_parseDate_year=$(( 10#${BASH_REMATCH[5]:-} ))
debug "regex match: ${tan}Month DD, YYYY${purple}"
# Month DD, YY
elif [[ "${date}" =~ ((january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec)[-\./_ ]+([0-9]{1,2})(nd|rd|th|st)?,?[-\./_ ]+([0-9]{2}))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[1]}"
_parseDate_month=$(_monthToNumber_ ${BASH_REMATCH[2]})
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[3]} ))
_parseDate_year="20$(( 10#${BASH_REMATCH[5]} ))"
debug "regex match: ${tan}Month DD, YY${purple}"
# DD Month YYYY
elif [[ "${date}" =~ (.*[^0-9]|^)(([0-9]{2})[-\./_ ]+(january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec),?[-\./_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day=$(( 10#"${BASH_REMATCH[3]}" ))
_parseDate_month="$(_monthToNumber_ "${BASH_REMATCH[4]}")"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year=$(( 10#"${BASH_REMATCH[5]}" ))
debug "regex match: ${tan}DD Month, YYYY${purple}"
# MM-DD-YYYY or DD-MM-YYYY
elif [[ "${date}" =~ (.*[^0-9]|^)(([ 0-9]{1,2})[-\.\/_ ]+([ 0-9]{1,2})[-\.\/_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
if [[ $(( 10#${BASH_REMATCH[3]} )) -lt 13 && \
$(( 10#${BASH_REMATCH[4]} )) -gt 12 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 32
]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year=$(( 10#${BASH_REMATCH[5]} ))
_parseDate_month=$(( 10#${BASH_REMATCH[3]} ))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[4]} ))
debug "regex match: ${tan}MM-DD-YYYY${purple}"
elif [[ $(( 10#${BASH_REMATCH[3]} )) -gt 12 && \
$(( 10#${BASH_REMATCH[3]} )) -lt 32 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 13
]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year=$(( 10#${BASH_REMATCH[5]} ))
_parseDate_month=$(( 10#${BASH_REMATCH[4]} ))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[3]} ))
debug "regex match: ${tan}DD-MM-YYYY${purple}"
elif [[ $(( 10#${BASH_REMATCH[3]} )) -lt 32 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 13
]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year=$(( 10#${BASH_REMATCH[5]} ))
_parseDate_month=$(( 10#${BASH_REMATCH[3]} ))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[4]} ))
debug "regex match: ${tan}MM-DD-YYYY${purple}"
else
shopt -u nocasematch
[[ $# -eq 0 ]] && {
error 'Missing required argument to _parseDate_()!'
return 1
fi
}
elif [[ "${date}" =~ (.*[^0-9]|^)(([0-9]{1,2})[-\.\/_ ]+([0-9]{1,2})[-\.\/_ ]+([0-9]{2}))([^0-9].*|$) ]]; then
local date="${1:-$(date +%F)}"
_parseDate_found="" _parseDate_year="" _parseDate_month="" _parseDate_monthName=""
_parseDate_day="" _parseDate_hour="" _parseDate_minute=""
if [[ $(( 10#${BASH_REMATCH[3]} )) -lt 13 && \
$(( 10#${BASH_REMATCH[4]} )) -gt 12 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 32
]]; then
shopt -s nocasematch #Use case-insensitive regex
debug "_parseDate_() input ${tan}$date${purple}"
# YYYY MM DD or YYYY-MM-DD
pat="(.*[^0-9]|^)((20[0-2][0-9])[-\.\/_ ]+([ 0-9]{1,2})[-\.\/_ ]+([ 0-9]{1,2}))([^0-9].*|$)"
if [[ ${date} =~ $pat ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year=$((10#${BASH_REMATCH[3]}))
_parseDate_month=$((10#${BASH_REMATCH[4]}))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$((10#${BASH_REMATCH[5]}))
debug "regex match: ${tan}YYYY-MM-DD${purple}"
# Month DD, YYYY
elif [[ ${date} =~ ((january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec)[-\./_ ]+([0-9]{1,2})(nd|rd|th|st)?,?[-\./_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[1]:-}"
_parseDate_month=$(_monthToNumber_ ${BASH_REMATCH[2]:-})
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month:-}")"
_parseDate_day=$((10#${BASH_REMATCH[3]:-}))
_parseDate_year=$((10#${BASH_REMATCH[5]:-}))
debug "regex match: ${tan}Month DD, YYYY${purple}"
# Month DD, YY
elif [[ ${date} =~ ((january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec)[-\./_ ]+([0-9]{1,2})(nd|rd|th|st)?,?[-\./_ ]+([0-9]{2}))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[1]}"
_parseDate_month=$(_monthToNumber_ ${BASH_REMATCH[2]})
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$((10#${BASH_REMATCH[3]}))
_parseDate_year="20$((10#${BASH_REMATCH[5]}))"
debug "regex match: ${tan}Month DD, YY${purple}"
# DD Month YYYY
elif [[ ${date} =~ (.*[^0-9]|^)(([0-9]{2})[-\./_ ]+(january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec),?[-\./_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day=$((10#"${BASH_REMATCH[3]}"))
_parseDate_month="$(_monthToNumber_ "${BASH_REMATCH[4]}")"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year=$((10#"${BASH_REMATCH[5]}"))
debug "regex match: ${tan}DD Month, YYYY${purple}"
# MM-DD-YYYY or DD-MM-YYYY
elif [[ ${date} =~ (.*[^0-9]|^)(([ 0-9]{1,2})[-\.\/_ ]+([ 0-9]{1,2})[-\.\/_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
if [[ $((10#${BASH_REMATCH[3]})) -lt 13 &&
$((10#${BASH_REMATCH[4]})) -gt 12 &&
$((10#${BASH_REMATCH[4]})) -lt 32 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year="20$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_month=$(( 10#${BASH_REMATCH[3]} ))
_parseDate_year=$((10#${BASH_REMATCH[5]}))
_parseDate_month=$((10#${BASH_REMATCH[3]}))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[4]} ))
_parseDate_day=$((10#${BASH_REMATCH[4]}))
debug "regex match: ${tan}MM-DD-YYYY${purple}"
elif [[ $(( 10#${BASH_REMATCH[3]} )) -gt 12 && \
$(( 10#${BASH_REMATCH[3]} )) -lt 32 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 13
]]; then
elif [[ $((10#${BASH_REMATCH[3]})) -gt 12 &&
$((10#${BASH_REMATCH[3]})) -lt 32 &&
$((10#${BASH_REMATCH[4]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year="20$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_month=$(( 10#${BASH_REMATCH[4]} ))
_parseDate_year=$((10#${BASH_REMATCH[5]}))
_parseDate_month=$((10#${BASH_REMATCH[4]}))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[3]} ))
_parseDate_day=$((10#${BASH_REMATCH[3]}))
debug "regex match: ${tan}DD-MM-YYYY${purple}"
elif [[ $(( 10#${BASH_REMATCH[3]} )) -lt 32 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 13
]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year="20$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_month=$(( 10#${BASH_REMATCH[3]} ))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$(( 10#${BASH_REMATCH[4]} ))
debug "regex match: ${tan}MM-DD-YYYY${purple}"
else
shopt -u nocasematch
return 1
fi
elif [[ $((10#${BASH_REMATCH[3]})) -lt 32 &&
$((10#${BASH_REMATCH[4]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year=$((10#${BASH_REMATCH[5]}))
_parseDate_month=$((10#${BASH_REMATCH[3]}))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$((10#${BASH_REMATCH[4]}))
debug "regex match: ${tan}MM-DD-YYYY${purple}"
else
shopt -u nocasematch
return 1
fi
# Month, YYYY
elif [[ "${date}" =~ ((january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec),?[-\./_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[1]}"
_parseDate_day="1"
_parseDate_month="$(_monthToNumber_ "${BASH_REMATCH[2]}")"
_parseDate_monthName="$(_numberToMonth_ $_parseDate_month)"
_parseDate_year="$(( 10#${BASH_REMATCH[3]} ))"
debug "regex match: ${tan}Month, YYYY${purple}"
elif [[ ${date} =~ (.*[^0-9]|^)(([0-9]{1,2})[-\.\/_ ]+([0-9]{1,2})[-\.\/_ ]+([0-9]{2}))([^0-9].*|$) ]]; then
# YYYYMMDDHHMM
elif [[ "${date}" =~ (.*[^0-9]|^)((20[0-2][0-9])([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_month="$(( 10#${BASH_REMATCH[4]} ))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="$(( 10#${BASH_REMATCH[3]} ))"
_parseDate_hour="$(( 10#${BASH_REMATCH[6]} ))"
_parseDate_minute="$(( 10#${BASH_REMATCH[7]} ))"
debug "regex match: ${tan}YYYYMMDDHHMM${purple}"
if [[ $((10#${BASH_REMATCH[3]})) -lt 13 &&
$((10#${BASH_REMATCH[4]})) -gt 12 &&
$((10#${BASH_REMATCH[4]})) -lt 32 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year="20$((10#${BASH_REMATCH[5]}))"
_parseDate_month=$((10#${BASH_REMATCH[3]}))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$((10#${BASH_REMATCH[4]}))
debug "regex match: ${tan}MM-DD-YYYY${purple}"
elif [[ $((10#${BASH_REMATCH[3]})) -gt 12 &&
$((10#${BASH_REMATCH[3]})) -lt 32 &&
$((10#${BASH_REMATCH[4]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year="20$((10#${BASH_REMATCH[5]}))"
_parseDate_month=$((10#${BASH_REMATCH[4]}))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$((10#${BASH_REMATCH[3]}))
debug "regex match: ${tan}DD-MM-YYYY${purple}"
elif [[ $((10#${BASH_REMATCH[3]})) -lt 32 &&
$((10#${BASH_REMATCH[4]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_year="20$((10#${BASH_REMATCH[5]}))"
_parseDate_month=$((10#${BASH_REMATCH[3]}))
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_day=$((10#${BASH_REMATCH[4]}))
debug "regex match: ${tan}MM-DD-YYYY${purple}"
else
shopt -u nocasematch
return 1
fi
# YYYYMMDDHH 1 2 3 4 5 6
elif [[ "${date}" =~ (.*[^0-9]|^)((20[0-2][0-9])([0-9]{2})([0-9]{2})([0-9]{2}))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_month="$(( 10#${BASH_REMATCH[4]} ))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="$(( 10#${BASH_REMATCH[3]} ))"
_parseDate_hour="${BASH_REMATCH[6]}"
_parseDate_minute="00"
debug "regex match: ${tan}YYYYMMDDHHMM${purple}"
# Month, YYYY
elif [[ ${date} =~ ((january|jan|ja|february|feb|fe|march|mar|ma|april|apr|ap|may|june|jun|july|jul|ju|august|aug|september|sep|october|oct|november|nov|december|dec),?[-\./_ ]+(20[0-2][0-9]))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[1]}"
_parseDate_day="1"
_parseDate_month="$(_monthToNumber_ "${BASH_REMATCH[2]}")"
_parseDate_monthName="$(_numberToMonth_ $_parseDate_month)"
_parseDate_year="$((10#${BASH_REMATCH[3]}))"
debug "regex match: ${tan}Month, YYYY${purple}"
# MMDDYYYY or YYYYMMDD or DDMMYYYY
# 1 2 3 4 5 6
elif [[ "${date}" =~ (.*[^0-9]|^)(([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))([^0-9].*|$) ]]; then
# YYYYMMDDHHMM
elif [[ ${date} =~ (.*[^0-9]|^)((20[0-2][0-9])([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$((10#${BASH_REMATCH[5]}))"
_parseDate_month="$((10#${BASH_REMATCH[4]}))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="$((10#${BASH_REMATCH[3]}))"
_parseDate_hour="$((10#${BASH_REMATCH[6]}))"
_parseDate_minute="$((10#${BASH_REMATCH[7]}))"
debug "regex match: ${tan}YYYYMMDDHHMM${purple}"
# YYYYMMDDHH 1 2 3 4 5 6
elif [[ ${date} =~ (.*[^0-9]|^)((20[0-2][0-9])([0-9]{2})([0-9]{2})([0-9]{2}))([^0-9].*|$) ]]; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$((10#${BASH_REMATCH[5]}))"
_parseDate_month="$((10#${BASH_REMATCH[4]}))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="$((10#${BASH_REMATCH[3]}))"
_parseDate_hour="${BASH_REMATCH[6]}"
_parseDate_minute="00"
debug "regex match: ${tan}YYYYMMDDHHMM${purple}"
# MMDDYYYY or YYYYMMDD or DDMMYYYY
# 1 2 3 4 5 6
elif [[ ${date} =~ (.*[^0-9]|^)(([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))([^0-9].*|$) ]]; then
# MMDDYYYY
if [[ $(( 10#${BASH_REMATCH[5]} )) -eq 20 && \
$(( 10#${BASH_REMATCH[3]} )) -lt 13 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 32
]]; then
if [[ $((10#${BASH_REMATCH[5]})) -eq 20 &&
$((10#${BASH_REMATCH[3]})) -lt 13 &&
$((10#${BASH_REMATCH[4]})) -lt 32 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$(( 10#${BASH_REMATCH[4]} ))"
_parseDate_month="$(( 10#${BASH_REMATCH[3]} ))"
_parseDate_day="$((10#${BASH_REMATCH[4]}))"
_parseDate_month="$((10#${BASH_REMATCH[3]}))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="${BASH_REMATCH[5]}${BASH_REMATCH[6]}"
debug "regex match: ${tan}MMDDYYYY${purple}"
# DDMMYYYY
elif [[ $(( 10#${BASH_REMATCH[5]} )) -eq 20 && \
$(( 10#${BASH_REMATCH[3]} )) -gt 12 && \
$(( 10#${BASH_REMATCH[3]} )) -lt 32 && \
$(( 10#${BASH_REMATCH[4]} )) -lt 13
]]; then
elif [[ $((10#${BASH_REMATCH[5]})) -eq 20 &&
$((10#${BASH_REMATCH[3]})) -gt 12 &&
$((10#${BASH_REMATCH[3]})) -lt 32 &&
$((10#${BASH_REMATCH[4]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$(( 10#${BASH_REMATCH[3]} ))"
_parseDate_month="$(( 10#${BASH_REMATCH[4]} ))"
_parseDate_day="$((10#${BASH_REMATCH[3]}))"
_parseDate_month="$((10#${BASH_REMATCH[4]}))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="${BASH_REMATCH[5]}${BASH_REMATCH[6]}"
debug "regex match: ${tan}DDMMYYYY${purple}"
# YYYYMMDD
elif [[ $(( 10#${BASH_REMATCH[3]} )) -eq 20 \
&& $(( 10#${BASH_REMATCH[6]} )) -gt 12 \
&& $(( 10#${BASH_REMATCH[6]} )) -lt 32 \
&& $(( 10#${BASH_REMATCH[5]} )) -lt 13 \
]]; then
elif [[ $((10#${BASH_REMATCH[3]})) -eq 20 &&
$((10#${BASH_REMATCH[6]})) -gt 12 &&
$((10#${BASH_REMATCH[6]})) -lt 32 &&
$((10#${BASH_REMATCH[5]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$(( 10#${BASH_REMATCH[6]} ))"
_parseDate_month="$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_day="$((10#${BASH_REMATCH[6]}))"
_parseDate_month="$((10#${BASH_REMATCH[5]}))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="${BASH_REMATCH[3]}${BASH_REMATCH[4]}"
debug "regex match: ${tan}YYYYMMDD${purple}"
# YYYYDDMM
elif [[ $(( 10#${BASH_REMATCH[3]} )) -eq 20 \
&& $(( 10#${BASH_REMATCH[5]} )) -gt 12 \
&& $(( 10#${BASH_REMATCH[5]} )) -lt 32 \
&& $(( 10#${BASH_REMATCH[6]} )) -lt 13 \
]]; then
elif [[ $((10#${BASH_REMATCH[3]})) -eq 20 &&
$((10#${BASH_REMATCH[5]})) -gt 12 &&
$((10#${BASH_REMATCH[5]})) -lt 32 &&
$((10#${BASH_REMATCH[6]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_month="$(( 10#${BASH_REMATCH[6]} ))"
_parseDate_day="$((10#${BASH_REMATCH[5]}))"
_parseDate_month="$((10#${BASH_REMATCH[6]}))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="${BASH_REMATCH[3]}${BASH_REMATCH[4]}"
debug "regex match: ${tan}YYYYMMDD${purple}"
# Assume YYYMMDD
elif [[ $(( 10#${BASH_REMATCH[3]} )) -eq 20 \
&& $(( 10#${BASH_REMATCH[6]} )) -lt 32 \
&& $(( 10#${BASH_REMATCH[5]} )) -lt 13 \
]]; then
elif [[ $((10#${BASH_REMATCH[3]})) -eq 20 &&
$((10#${BASH_REMATCH[6]})) -lt 32 &&
$((10#${BASH_REMATCH[5]})) -lt 13 ]] \
; then
_parseDate_found="${BASH_REMATCH[2]}"
_parseDate_day="$(( 10#${BASH_REMATCH[6]} ))"
_parseDate_month="$(( 10#${BASH_REMATCH[5]} ))"
_parseDate_day="$((10#${BASH_REMATCH[6]}))"
_parseDate_month="$((10#${BASH_REMATCH[5]}))"
_parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
_parseDate_year="${BASH_REMATCH[3]}${BASH_REMATCH[4]}"
debug "regex match: ${tan}YYYYMMDD${purple}"
else
shopt -u nocasematch
return 1
shopt -u nocasematch
return 1
fi
# # MMDD or DDYY
# elif [[ "$date" =~ .*(([0-9]{2})([0-9]{2})).* ]]; then
# debug "regex match: ${tan}MMDD or DDMM${purple}"
# _parseDate_found="${BASH_REMATCH[1]}"
# # MMDD or DDYY
# elif [[ "$date" =~ .*(([0-9]{2})([0-9]{2})).* ]]; then
# debug "regex match: ${tan}MMDD or DDMM${purple}"
# _parseDate_found="${BASH_REMATCH[1]}"
# # Figure out if days are months or vice versa
# if [[ $(( 10#${BASH_REMATCH[2]} )) -gt 12 \
# && $(( 10#${BASH_REMATCH[2]} )) -lt 32 \
# && $(( 10#${BASH_REMATCH[3]} )) -lt 13 \
# ]]; then
# _parseDate_day="$(( 10#${BASH_REMATCH[2]} ))"
# _parseDate_month="$(( 10#${BASH_REMATCH[3]} ))"
# _parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
# _parseDate_year="$(date +%Y )"
# elif [[ $(( 10#${BASH_REMATCH[2]} )) -lt 13 \
# && $(( 10#${BASH_REMATCH[3]} )) -lt 32 \
# ]]; then
# _parseDate_day="$(( 10#${BASH_REMATCH[3]} ))"
# _parseDate_month="$(( 10#${BASH_REMATCH[2]} ))"
# _parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
# _parseDate_year="$(date +%Y )"
# else
# shopt -u nocasematch
# return 1
# fi
else
shopt -u nocasematch
return 1
fi
[[ -z ${_parseDate_year:-} ]] && {
shopt -u nocasematch
return 1
}
((_parseDate_month >= 1 && _parseDate_month <= 12)) || {
shopt -u nocasematch
return 1
}
((_parseDate_day >= 1 && _parseDate_day <= 31)) || {
shopt -u nocasematch
return 1
}
debug "${tan}\$_parseDate_found: ${_parseDate_found}${purple}"
debug "${tan}\$_parseDate_year: ${_parseDate_year}${purple}"
debug "${tan}\$_parseDate_month: ${_parseDate_month}${purple}"
debug "${tan}\$_parseDate_monthName: ${_parseDate_monthName}${purple}"
debug "${tan}\$_parseDate_day: ${_parseDate_day}${purple}"
[[ -z ${_parseDate_hour:-} ]] || debug "${tan}\$_parseDate_hour: ${_parseDate_hour}${purple}"
[[ -z ${_parseDate_minute:-} ]] || debug "${tan}\$_parseDate_minute: ${_parseDate_minute}${purple}"
# # Figure out if days are months or vice versa
# if [[ $(( 10#${BASH_REMATCH[2]} )) -gt 12 \
# && $(( 10#${BASH_REMATCH[2]} )) -lt 32 \
# && $(( 10#${BASH_REMATCH[3]} )) -lt 13 \
# ]]; then
# _parseDate_day="$(( 10#${BASH_REMATCH[2]} ))"
# _parseDate_month="$(( 10#${BASH_REMATCH[3]} ))"
# _parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
# _parseDate_year="$(date +%Y )"
# elif [[ $(( 10#${BASH_REMATCH[2]} )) -lt 13 \
# && $(( 10#${BASH_REMATCH[3]} )) -lt 32 \
# ]]; then
# _parseDate_day="$(( 10#${BASH_REMATCH[3]} ))"
# _parseDate_month="$(( 10#${BASH_REMATCH[2]} ))"
# _parseDate_monthName="$(_numberToMonth_ "${_parseDate_month}")"
# _parseDate_year="$(date +%Y )"
# else
# shopt -u nocasematch
# return 1
# fi
else
shopt -u nocasematch
return 1
fi
[[ -z ${_parseDate_year:-} ]] && { shopt -u nocasematch; return 1 ; }
(( _parseDate_month >= 1 && _parseDate_month <= 12 )) || { shopt -u nocasematch; return 1 ; }
(( _parseDate_day >= 1 && _parseDate_day <= 31 )) || { shopt -u nocasematch; return 1 ; }
debug "${tan}\$_parseDate_found: ${_parseDate_found}${purple}"
debug "${tan}\$_parseDate_year: ${_parseDate_year}${purple}"
debug "${tan}\$_parseDate_month: ${_parseDate_month}${purple}"
debug "${tan}\$_parseDate_monthName: ${_parseDate_monthName}${purple}"
debug "${tan}\$_parseDate_day: ${_parseDate_day}${purple}"
[[ -z ${_parseDate_hour:-} ]] || debug "${tan}\$_parseDate_hour: ${_parseDate_hour}${purple}"
[[ -z ${_parseDate_minute:-} ]] || debug "${tan}\$_parseDate_minute: ${_parseDate_minute}${purple}"
shopt -u nocasematch
# Output results for BATS tests
if [ "${automated_test_in_progress:-}" ]; then
echo "_parseDate_found: ${_parseDate_found}"
echo "_parseDate_year: ${_parseDate_year}"
echo "_parseDate_month: ${_parseDate_month}"
echo "_parseDate_monthName: ${_parseDate_monthName}"
echo "_parseDate_day: ${_parseDate_day}"
echo "_parseDate_hour: ${_parseDate_hour}"
echo "_parseDate_minute: ${_parseDate_minute}"
fi
# Output results for BATS tests
if [ "${automated_test_in_progress:-}" ]; then
echo "_parseDate_found: ${_parseDate_found}"
echo "_parseDate_year: ${_parseDate_year}"
echo "_parseDate_month: ${_parseDate_month}"
echo "_parseDate_monthName: ${_parseDate_monthName}"
echo "_parseDate_day: ${_parseDate_day}"
echo "_parseDate_hour: ${_parseDate_hour}"
echo "_parseDate_minute: ${_parseDate_minute}"
fi
}
_formatDate_() {
# DESC: Reformats dates into user specified formats
# ARGS: $1 (Required) - Date to be formatted
# $2 (Optional) - Format in any format accepted by bash's date command. Examples listed below.
# %F - YYYY-MM-DD
# %D - MM/DD/YY
# %a - Name of weekday in short (like Sun, Mon, Tue, Wed, Thu, Fri, Sat)
# %A - Name of weekday in full (like Sunday, Monday, Tuesday)
# '+%m %d, %Y' - 12 27, 2019
# OUTS: Echo result to STDOUT
# USAGE: _formatDate_ "Jan 10, 2019" "%D"
# NOTE: Defaults to YYYY-MM-DD or $(date +%F)
# DESC: Reformats dates into user specified formats
# ARGS: $1 (Required) - Date to be formatted
# $2 (Optional) - Format in any format accepted by bash's date command. Examples listed below.
# %F - YYYY-MM-DD
# %D - MM/DD/YY
# %a - Name of weekday in short (like Sun, Mon, Tue, Wed, Thu, Fri, Sat)
# %A - Name of weekday in full (like Sunday, Monday, Tuesday)
# '+%m %d, %Y' - 12 27, 2019
# OUTS: Echo result to STDOUT
# USAGE: _formatDate_ "Jan 10, 2019" "%D"
# NOTE: Defaults to YYYY-MM-DD or $(date +%F)
[[ $# -eq 0 ]] && {
error 'Missing required argument to _formatDate_()'
return 1
}
[[ $# -eq 0 ]] && {
error 'Missing required argument to _formatDate_()'
return 1
}
local d="${1}"
local format="${2:-%F}"
format="${format//+/}"
local d="${1}"
local format="${2:-%F}"
format="${format//+/}"
if command -v gdate >/dev/null 2>&1; then
gdate -d "${d}" "+${format}"
else
date -d "${d}" "+${format}"
fi
if command -v gdate >/dev/null 2>&1; then
gdate -d "${d}" "+${format}"
else
date -d "${d}" "+${format}"
fi
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,39 @@
# Functions for use on computers running MacOS
_haveScriptableFinder_() {
# DESC: Determine whether we can script the Finder or not
# ARGS: None
# OUTS: true/false
# DESC: Determine whether we can script the Finder or not
# ARGS: None
# OUTS: true/false
local finder_pid
finder_pid="$(pgrep -f /System/Library/CoreServices/Finder.app | head -n 1)"
local finder_pid
finder_pid="$(pgrep -f /System/Library/CoreServices/Finder.app | head -n 1)"
if [[ (${finder_pid} -gt 1) && ("${STY-}" == "") ]]; then
return 0
else
return 1
fi
if [[ (${finder_pid} -gt 1) && (${STY-} == "") ]]; then
return 0
else
return 1
fi
}
_guiInput_() {
# DESC: Ask for user input using a Mac dialog box
# ARGS: $1 (Optional) - Text in dialogue box (Default: Password)
# OUTS: None
# NOTE: https://github.com/herrbischoff/awesome-osx-command-line/blob/master/functions.md
if _haveScriptableFinder_; then
guiPrompt="${1:-Password:}"
guiInput=$(
osascript &>/dev/null <<EOF
# DESC: Ask for user input using a Mac dialog box
# ARGS: $1 (Optional) - Text in dialogue box (Default: Password)
# OUTS: None
# NOTE: https://github.com/herrbischoff/awesome-osx-command-line/blob/master/functions.md
if _haveScriptableFinder_; then
guiPrompt="${1:-Password:}"
guiInput=$(
osascript &>/dev/null <<EOF
tell application "System Events"
activate
text returned of (display dialog "${guiPrompt}" default answer "" with hidden answer)
end tell
EOF
)
echo -n "${guiInput}"
else
error "No GUI input without macOS"
return 1
fi
)
echo -n "${guiInput}"
else
error "No GUI input without macOS"
return 1
fi
}
}

View File

@@ -1,71 +1,73 @@
_fromSeconds_() {
# DESC: Convert seconds to HH:MM:SS
# ARGS: $1 (Required) - Time in seconds
# OUTS: Print HH:MM:SS to STDOUT
# USAGE: _convertSecs_ "SECONDS"
# To compute the time it takes a script to run:
# STARTTIME=$(date +"%s")
# ENDTIME=$(date +"%s")
# TOTALTIME=$(($ENDTIME-$STARTTIME)) # human readable time
# _convertSecs_ "$TOTALTIME"
# DESC: Convert seconds to HH:MM:SS
# ARGS: $1 (Required) - Time in seconds
# OUTS: Print HH:MM:SS to STDOUT
# USAGE: _convertSecs_ "SECONDS"
# To compute the time it takes a script to run:
# STARTTIME=$(date +"%s")
# ENDTIME=$(date +"%s")
# TOTALTIME=$(($ENDTIME-$STARTTIME)) # human readable time
# _convertSecs_ "$TOTALTIME"
((h = ${1} / 3600))
((m = (${1} % 3600) / 60))
((s = ${1} % 60))
printf "%02d:%02d:%02d\n" $h $m $s
((h = ${1} / 3600))
((m = (${1} % 3600) / 60))
((s = ${1} % 60))
printf "%02d:%02d:%02d\n" $h $m $s
}
_toSeconds_() {
# DESC: Converts HH:MM:SS to seconds
# ARGS: $1 (Required) - Time in HH:MM:SS
# OUTS: Print seconds to STDOUT
# USAGE: _toSeconds_ "01:00:00"
# NOTE: Acceptable Input Formats
# 24 12 09
# 12,12,09
# 12;12;09
# 12:12:09
# 12-12-09
# 12H12M09S
# 12h12m09s
# DESC: Converts HH:MM:SS to seconds
# ARGS: $1 (Required) - Time in HH:MM:SS
# OUTS: Print seconds to STDOUT
# USAGE: _toSeconds_ "01:00:00"
# NOTE: Acceptable Input Formats
# 24 12 09
# 12,12,09
# 12;12;09
# 12:12:09
# 12-12-09
# 12H12M09S
# 12h12m09s
local saveIFS
local saveIFS
local h
local m
local s
if [[ "$1" =~ [0-9]{1,2}(:|,|-|_|,| |[hHmMsS])[0-9]{1,2}(:|,|-|_|,| |[hHmMsS])[0-9]{1,2} ]]; then
saveIFS="$IFS"
IFS=":,;-_, HhMmSs" read -r h m s <<< "$1"
IFS="$saveIFS"
else
h="$1"
m="$2"
s="$3"
fi
if [[ $1 =~ [0-9]{1,2}(:|,|-|_|,| |[hHmMsS])[0-9]{1,2}(:|,|-|_|,| |[hHmMsS])[0-9]{1,2} ]]; then
saveIFS="$IFS"
IFS=":,;-_, HhMmSs" read -r h m s <<<"$1"
IFS="$saveIFS"
else
h="$1"
m="$2"
s="$3"
fi
echo $(( 10#$h * 3600 + 10#$m * 60 + 10#$s ))
echo $((10#$h * 3600 + 10#$m * 60 + 10#$s))
}
_countdown_() {
# DESC: Sleep for a specified amount of time
# ARGS: $1 (Optional) - Total seconds to sleep for(Default is 10)
# $2 (Optional) - Increment to count down
# $3 (Optional) - Message to print at each increment (default is ...)
# OUTS: None
# USAGE: _countdown_ 10 1 "Waiting for cache to invalidate"
# DESC: Sleep for a specified amount of time
# ARGS: $1 (Optional) - Total seconds to sleep for(Default is 10)
# $2 (Optional) - Increment to count down
# $3 (Optional) - Message to print at each increment (default is ...)
# OUTS: None
# USAGE: _countdown_ 10 1 "Waiting for cache to invalidate"
local i ii t
local n=${1:-10}
local stime=${2:-1}
local message="${3:-...}"
((t = n + 1))
local i ii t
local n=${1:-10}
local stime=${2:-1}
local message="${3:-...}"
((t = n + 1))
for ((i = 1; i <= n; i++)); do
((ii = t - i))
if declare -f "info" &>/dev/null 2>&1; then
info "${message} ${ii}"
else
echo "${message} ${ii}"
fi
sleep $stime
done
for ((i = 1; i <= n; i++)); do
((ii = t - i))
if declare -f "info" &>/dev/null 2>&1; then
info "${message} ${ii}"
else
echo "${message} ${ii}"
fi
sleep $stime
done
}

View File

@@ -1,148 +1,148 @@
_haveInternet_() {
# DESC: Tests to see if there is an active Internet connection
# ARGS: None
# OUTS: None
# USAGE: _haveInternet_ && [SOMETHING]
# NOTE: https://stackoverflow.com/questions/929368/
# DESC: Tests to see if there is an active Internet connection
# ARGS: None
# OUTS: None
# USAGE: _haveInternet_ && [SOMETHING]
# NOTE: https://stackoverflow.com/questions/929368/
if command -v fping &>/dev/null; then
fping 1.1.1.1 &>/dev/null \
&& return 0 \
|| return 1
elif ping -t 2 -c 1 1 1.1.1.1 &>/dev/null; then
return 0
elif command -v route &>/dev/null; then
local GATEWAY="$(route -n get default | grep gateway)"
ping -t 2 -c 1 "$(echo "${GATEWAY}" | cut -d ':' -f 2)" &>/dev/null \
&& return 0 \
|| return 1
elif command -v ip &>/dev/null; then
ping -t 2 -c 1 "$(ip r | grep default | cut -d ' ' -f 3)" &>/dev/null \
&& return 0 \
|| return 1
else
return 1
fi
if command -v fping &>/dev/null; then
fping 1.1.1.1 &>/dev/null \
&& return 0 \
|| return 1
elif ping -t 2 -c 1 1 1.1.1.1 &>/dev/null; then
return 0
elif command -v route &>/dev/null; then
local GATEWAY="$(route -n get default | grep gateway)"
ping -t 2 -c 1 "$(echo "${GATEWAY}" | cut -d ':' -f 2)" &>/dev/null \
&& return 0 \
|| return 1
elif command -v ip &>/dev/null; then
ping -t 2 -c 1 "$(ip r | grep default | cut -d ' ' -f 3)" &>/dev/null \
&& return 0 \
|| return 1
else
return 1
fi
}
_httpStatus_() {
# DESC: Report the HTTP status of a specified URL
# ARGS: $1 (Required) - URL (will work fine without https:// prefix)
# $2 (Optional) - Seconds to wait until timeout (Default is 3)
# $3 (Optional) - either '--code' or '--status' (default)
# $4 (optional) - CURL opts separated by spaces (Use -L to follow redirects)
# OUTS: Prints output to STDOUT
# USAGE: _httpStatus_ URL [timeout] [--code or --status] [curl opts]
# NOTE: https://gist.github.com/rsvp/1171304
#
# Example: $ _httpStatus_ bit.ly
# 301 Redirection: Moved Permanently
#
# Example: $ _httpStatus_ www.google.com 100 --code
local code
local status
# DESC: Report the HTTP status of a specified URL
# ARGS: $1 (Required) - URL (will work fine without https:// prefix)
# $2 (Optional) - Seconds to wait until timeout (Default is 3)
# $3 (Optional) - either '--code' or '--status' (default)
# $4 (optional) - CURL opts separated by spaces (Use -L to follow redirects)
# OUTS: Prints output to STDOUT
# USAGE: _httpStatus_ URL [timeout] [--code or --status] [curl opts]
# NOTE: https://gist.github.com/rsvp/1171304
#
# Example: $ _httpStatus_ bit.ly
# 301 Redirection: Moved Permanently
#
# Example: $ _httpStatus_ www.google.com 100 --code
local code
local status
local saveIFS=${IFS}
IFS=$' \n\t'
local saveIFS=${IFS}
IFS=$' \n\t'
local url=${1:?_httpStatus_ needs an url}
local timeout=${2:-'3'}
local flag=${3:-'--status'}
local arg4=${4:-''}
local arg5=${5:-''}
local arg6=${6:-''}
local arg7=${7:-''}
local curlops="${arg4} ${arg5} ${arg6} ${arg7}"
local url=${1:?_httpStatus_ needs an url}
local timeout=${2:-'3'}
local flag=${3:-'--status'}
local arg4=${4:-''}
local arg5=${5:-''}
local arg6=${6:-''}
local arg7=${7:-''}
local curlops="${arg4} ${arg5} ${arg6} ${arg7}"
# __________ get the CODE which is numeric:
code=$(echo "$(curl --write-out %{http_code} --silent --connect-timeout "${timeout}" \
--no-keepalive "${curlops}" --output /dev/null "${url}")")
# __________ get the CODE which is numeric:
code=$(echo "$(curl --write-out %{http_code} --silent --connect-timeout "${timeout}" \
--no-keepalive "${curlops}" --output /dev/null "${url}")")
# __________ get the STATUS (from code) which is human interpretable:
case $code in
000) status="Not responding within ${timeout} seconds" ;;
100) status="Informational: Continue" ;;
101) status="Informational: Switching Protocols" ;;
200) status="Successful: OK within ${timeout} seconds" ;;
201) status="Successful: Created" ;;
202) status="Successful: Accepted" ;;
203) status="Successful: Non-Authoritative Information" ;;
204) status="Successful: No Content" ;;
205) status="Successful: Reset Content" ;;
206) status="Successful: Partial Content" ;;
300) status="Redirection: Multiple Choices" ;;
301) status="Redirection: Moved Permanently" ;;
302) status="Redirection: Found residing temporarily under different URI" ;;
303) status="Redirection: See Other" ;;
304) status="Redirection: Not Modified" ;;
305) status="Redirection: Use Proxy" ;;
306) status="Redirection: status not defined" ;;
307) status="Redirection: Temporary Redirect" ;;
400) status="Client Error: Bad Request" ;;
401) status="Client Error: Unauthorized" ;;
402) status="Client Error: Payment Required" ;;
403) status="Client Error: Forbidden" ;;
404) status="Client Error: Not Found" ;;
405) status="Client Error: Method Not Allowed" ;;
406) status="Client Error: Not Acceptable" ;;
407) status="Client Error: Proxy Authentication Required" ;;
408) status="Client Error: Request Timeout within ${timeout} seconds" ;;
409) status="Client Error: Conflict" ;;
410) status="Client Error: Gone" ;;
411) status="Client Error: Length Required" ;;
412) status="Client Error: Precondition Failed" ;;
413) status="Client Error: Request Entity Too Large" ;;
414) status="Client Error: Request-URI Too Long" ;;
415) status="Client Error: Unsupported Media Type" ;;
416) status="Client Error: Requested Range Not Satisfiable" ;;
417) status="Client Error: Expectation Failed" ;;
500) status="Server Error: Internal Server Error" ;;
501) status="Server Error: Not Implemented" ;;
502) status="Server Error: Bad Gateway" ;;
503) status="Server Error: Service Unavailable" ;;
504) status="Server Error: Gateway Timeout within ${timeout} seconds" ;;
505) status="Server Error: HTTP Version Not Supported" ;;
*) die "httpstatus: status not defined." ;;
esac
# __________ get the STATUS (from code) which is human interpretable:
case $code in
000) status="Not responding within ${timeout} seconds" ;;
100) status="Informational: Continue" ;;
101) status="Informational: Switching Protocols" ;;
200) status="Successful: OK within ${timeout} seconds" ;;
201) status="Successful: Created" ;;
202) status="Successful: Accepted" ;;
203) status="Successful: Non-Authoritative Information" ;;
204) status="Successful: No Content" ;;
205) status="Successful: Reset Content" ;;
206) status="Successful: Partial Content" ;;
300) status="Redirection: Multiple Choices" ;;
301) status="Redirection: Moved Permanently" ;;
302) status="Redirection: Found residing temporarily under different URI" ;;
303) status="Redirection: See Other" ;;
304) status="Redirection: Not Modified" ;;
305) status="Redirection: Use Proxy" ;;
306) status="Redirection: status not defined" ;;
307) status="Redirection: Temporary Redirect" ;;
400) status="Client Error: Bad Request" ;;
401) status="Client Error: Unauthorized" ;;
402) status="Client Error: Payment Required" ;;
403) status="Client Error: Forbidden" ;;
404) status="Client Error: Not Found" ;;
405) status="Client Error: Method Not Allowed" ;;
406) status="Client Error: Not Acceptable" ;;
407) status="Client Error: Proxy Authentication Required" ;;
408) status="Client Error: Request Timeout within ${timeout} seconds" ;;
409) status="Client Error: Conflict" ;;
410) status="Client Error: Gone" ;;
411) status="Client Error: Length Required" ;;
412) status="Client Error: Precondition Failed" ;;
413) status="Client Error: Request Entity Too Large" ;;
414) status="Client Error: Request-URI Too Long" ;;
415) status="Client Error: Unsupported Media Type" ;;
416) status="Client Error: Requested Range Not Satisfiable" ;;
417) status="Client Error: Expectation Failed" ;;
500) status="Server Error: Internal Server Error" ;;
501) status="Server Error: Not Implemented" ;;
502) status="Server Error: Bad Gateway" ;;
503) status="Server Error: Service Unavailable" ;;
504) status="Server Error: Gateway Timeout within ${timeout} seconds" ;;
505) status="Server Error: HTTP Version Not Supported" ;;
*) die "httpstatus: status not defined." ;;
esac
case ${flag} in
--status) echo "${code} ${status}" ;;
-s) echo "${code} ${status}" ;;
--code) echo "${code}" ;;
-c) echo "${code}" ;;
*) echo " httpstatus: bad flag" && _safeExit_ ;;
esac
case ${flag} in
--status) echo "${code} ${status}" ;;
-s) echo "${code} ${status}" ;;
--code) echo "${code}" ;;
-c) echo "${code}" ;;
*) echo " httpstatus: bad flag" && _safeExit_ ;;
esac
IFS="${saveIFS}"
IFS="${saveIFS}"
}
_pushover_() {
# DESC: Sends a notification via Pushover
# ARGS: $1 (Required) - Title of notification
# $2 (Required) - Body of notification
# OUTS: None
# USAGE: _pushover_ "Title Goes Here" "Message Goes Here"
# NOTE: The variables for the two API Keys must have valid values
# Credit: http://ryonsherman.blogspot.com/2012/10/shell-script-to-send-pushover.html
# DESC: Sends a notification via Pushover
# ARGS: $1 (Required) - Title of notification
# $2 (Required) - Body of notification
# OUTS: None
# USAGE: _pushover_ "Title Goes Here" "Message Goes Here"
# NOTE: The variables for the two API Keys must have valid values
# Credit: http://ryonsherman.blogspot.com/2012/10/shell-script-to-send-pushover.html
local PUSHOVERURL
local API_KEY
local USER_KEY
local DEVICE
local TITLE
local MESSAGE
local PUSHOVERURL
local API_KEY
local USER_KEY
local DEVICE
local TITLE
local MESSAGE
PUSHOVERURL="https://api.pushover.net/1/messages.json"
API_KEY="${PUSHOVER_API_KEY}"
USER_KEY="${PUSHOVER_USER_KEY}"
DEVICE=""
TITLE="${1}"
MESSAGE="${2}"
curl \
-F "token=${API_KEY}" \
-F "user=${USER_KEY}" \
-F "device=${DEVICE}" \
-F "title=${TITLE}" \
-F "message=${MESSAGE}" \
"${PUSHOVERURL}" >/dev/null 2>&1
PUSHOVERURL="https://api.pushover.net/1/messages.json"
API_KEY="${PUSHOVER_API_KEY}"
USER_KEY="${PUSHOVER_USER_KEY}"
DEVICE=""
TITLE="${1}"
MESSAGE="${2}"
curl \
-F "token=${API_KEY}" \
-F "user=${USER_KEY}" \
-F "device=${DEVICE}" \
-F "title=${TITLE}" \
-F "message=${MESSAGE}" \
"${PUSHOVERURL}" >/dev/null 2>&1
}

View File

@@ -2,288 +2,292 @@
# Some were adapted from https://github.com/jmcantrell/bashful
_cleanString_() {
# DESC: Cleans a string of text
# ARGS: $1 (Required) - String to be cleaned
# $2 (optional) - Specific characters to be cleaned (separated by commas,
# escape regex special chars)
# OPTS: -l Forces all text to lowercase
# -u Forces all text to uppercase
# -a Removes all non-alphanumeric characters except for spaces and dashes
# -p Replace one character with another (separated by commas) (escape regex characters)
# -s In combination with -a, replaces characters with a space
# OUTS: Prints result to STDOUT
# USAGE: _cleanString_ [OPT] [STRING] [CHARS TO REPLACE]
# _cleanString_ -p " ,-" [STRING] [CHARS TO REPLACE]
# NOTES: Always cleaned:
# - leading white space
# - trailing white space
# - multiple spaces become a single space
# - remove spaces before and aftrer -_
# DESC: Cleans a string of text
# ARGS: $1 (Required) - String to be cleaned
# $2 (optional) - Specific characters to be removed (separated by commas,
# escape regex special chars)
# OPTS: -l Forces all text to lowercase
# -u Forces all text to uppercase
# -a Removes all non-alphanumeric characters except for spaces and dashes
# -p Replace one character with another (separated by commas) (escape regex characters)
# -s In combination with -a, replaces characters with a space
# OUTS: Prints result to STDOUT
# USAGE: _cleanString_ [OPT] [STRING] [CHARS TO REMOVE]
# _cleanString_ -p " ,-" [STRING] [CHARS TO REMOVE]
# NOTES: Always cleaned:
# - leading white space
# - trailing white space
# - multiple spaces become a single space
# - remove spaces before and aftrer -_
local opt
local lc=false
local uc=false
local alphanumeric=false
local replace=false
local us=false
local opt
local lc=false
local uc=false
local alphanumeric=false
local replace=false
local us=false
local OPTIND=1
while getopts ":lLuUaAsSpP" opt; do
case $opt in
l | L) lc=true ;;
u | U) uc=true ;;
a | A) alphanumeric=true ;;
s | S) us=true ;;
p | P)
shift
local pairs=()
IFS=',' read -r -a pairs <<<"$1"
replace=true ;;
*)
{
error "Unrecognized option '$1' passed to _execute. Exiting."
return 1
}
;;
esac
done
shift $((OPTIND - 1))
local OPTIND=1
while getopts ":lLuUaAsSpP" opt; do
case $opt in
l | L) lc=true ;;
u | U) uc=true ;;
a | A) alphanumeric=true ;;
s | S) us=true ;;
p | P)
shift
local pairs=()
IFS=',' read -r -a pairs <<<"$1"
replace=true
;;
*)
{
error "Unrecognized option '$1' passed to _execute. Exiting."
return 1
}
;;
esac
done
shift $((OPTIND - 1))
[[ $# -lt 1 ]] && fatal 'Missing required argument to _cleanString_()!'
[[ $# -lt 1 ]] && fatal 'Missing required argument to _cleanString_()!'
local string="${1}"
local userChars="${2:-}"
local string="${1}"
local userChars="${2:-}"
local arrayToClean=()
IFS=',' read -r -a arrayToClean <<<"${userChars}"
local arrayToClean=()
IFS=',' read -r -a arrayToClean <<<"${userChars}"
# trim trailing/leading white space and duplicate spaces/tabs
string="$(echo "${string}" | awk '{$1=$1};1')"
# trim trailing/leading white space and duplicate spaces/tabs
string="$(echo "${string}" | awk '{$1=$1};1')"
local i
for i in "${arrayToClean[@]}"; do
debug "cleaning: $i"
string="$(echo "${string}" | sed "s/$i//g")"
done
local i
for i in "${arrayToClean[@]}"; do
debug "cleaning: $i"
string="$(echo "${string}" | sed "s/$i//g")"
done
("${lc}") \
&& string="$(echo "${string}" | tr '[:upper:]' '[:lower:]')"
("${lc}") \
&& string="$(echo "${string}" | tr '[:upper:]' '[:lower:]')"
("${uc}") \
&& string="$(echo "${string}" | tr '[:lower:]' '[:upper:]')"
("${uc}") \
&& string="$(echo "${string}" | tr '[:lower:]' '[:upper:]')"
if "${alphanumeric}" && "${us}"; then
string="$(echo "${string}" | tr -c '[:alnum:] -_' ' ')"
elif "${alphanumeric}"; then
string="$(echo "${string}" | sed "s/[^a-zA-Z0-9 -_]//g")"
fi
if "${alphanumeric}" && "${us}"; then
string="$(echo "${string}" | tr -c '[:alnum:]_ -' ' ')"
elif "${alphanumeric}"; then
string="$(echo "${string}" | sed "s/[^a-zA-Z0-9_ \-]//g")"
fi
if "${replace}"; then
string="$(echo "${string}" | sed "s/${pairs[0]}/${pairs[1]}/g")"
fi
if "${replace}"; then
string="$(echo "${string}" | sed "s/${pairs[0]}/${pairs[1]}/g")"
fi
# trim trailing/leading white space and duplicate dashes
string="$(echo "${string}" | tr -s '-')"
string="$(echo "${string}" | sed -E 's/([-_]) /\1/g' | sed -E 's/ ([-_])/\1/g')"
string="$(echo "${string}" | awk '{$1=$1};1')"
# trim trailing/leading white space and duplicate dashes
string="$(echo "${string}" | tr -s '-' | tr -s '_')"
string="$(echo "${string}" | sed -E 's/([_\-]) /\1/g' | sed -E 's/ ([_\-])/\1/g')"
string="$(echo "${string}" | awk '{$1=$1};1')"
printf "%s\n" "${string}"
printf "%s\n" "${string}"
}
_stopWords_() {
# DESC: Removes common stopwords from a string
# ARGS: $1 (Required) - String to parse
# $2 (Optional) - Additional stopwords (comma separated)
# OUTS: Prints cleaned string to STDOUT
# USAGE: cleanName="$(_stopWords_ "[STRING]" "[MORE,STOP,WORDS]")"
# NOTE: Requires a stopwords file in sed format (expected at: ~/.sed/stopwords.sed)
# DESC: Removes common stopwords from a string
# ARGS: $1 (Required) - String to parse
# $2 (Optional) - Additional stopwords (comma separated)
# OUTS: Prints cleaned string to STDOUT
# USAGE: cleanName="$(_stopWords_ "[STRING]" "[MORE,STOP,WORDS]")"
# NOTE: Requires a stopwords file in sed format (expected at: ~/.sed/stopwords.sed)
[[ $# -lt 1 ]] && {
warning 'Missing required argument to _stripCommonWords_!'
return 1
warning 'Missing required argument to _stripCommonWords_!'
return 1
}
[ "$(command -v gsed)" ] || {
error "Can not continue without gsed. Use '${YELLOW}brew install gnu-sed${reset}'"
return 1
}
if command -v gsed &>/dev/null; then
local SED_COMMAND="gsed"
elif sed --version | grep GNU &>/dev/null; then
local SED_COMMAND="sed"
else
error "Can not continue without gnu sed. Use '${YELLOW}brew install gnu-sed${reset} on a Mac or install with your package manager'"
return 1
fi
local string="${1}"
local sedFile="${HOME}/.sed/stopwords.sed"
if [ -f "${sedFile}" ]; then
string="$(echo "${string}" | gsed -f "${sedFile}")"
string="$(echo "${string}" | ${SED_COMMAND} -f "${sedFile}")"
else
debug "Missing sedfile in _stopWords_()"
debug "Missing sedfile in _stopWords_()"
fi
declare -a localStopWords=()
IFS=',' read -r -a localStopWords <<<"${2:-}"
if [[ ${#localStopWords[@]} -gt 0 ]]; then
for w in "${localStopWords[@]}"; do
string="$(echo "$string" | gsed -E "s/$w//gI")"
done
for w in "${localStopWords[@]}"; do
string="$(echo "${string}" | ${SED_COMMAND} -E "s/\b${w}\b//gI")"
done
fi
# Remove double spaces and trim left/right
string="$(echo "$string" | sed -E 's/[ ]{2,}/ /g' | _ltrim_ | _rtrim_)"
string="$(echo "${string}" | ${SED_COMMAND} -E 's/[ ]{2,}/ /g' | _ltrim_ | _rtrim_)"
echo "${string}"
}
_escape_() {
# DESC: Escapes a string by adding \ before special chars
# ARGS: $@ (Required) - String to be escaped
# OUTS: Prints output to STDOUT
# USAGE: _escape_ "Some text here"
# DESC: Escapes a string by adding \ before special chars
# ARGS: $@ (Required) - String to be escaped
# OUTS: Prints output to STDOUT
# USAGE: _escape_ "Some text here"
# shellcheck disable=2001
echo "${@}" | sed 's/[]\.|$[ (){}?+*^]/\\&/g'
# shellcheck disable=2001
echo "${@}" | sed 's/[]\.|$[ (){}?+*^]/\\&/g'
}
_htmlDecode_() {
# DESC: Decode HTML characters with sed
# ARGS: $1 (Required) - String to be decoded
# OUTS: Prints output to STDOUT
# USAGE: _htmlDecode_ <string>
# NOTE: Must have a sed file containing replacements
# DESC: Decode HTML characters with sed
# ARGS: $1 (Required) - String to be decoded
# OUTS: Prints output to STDOUT
# USAGE: _htmlDecode_ <string>
# NOTE: Must have a sed file containing replacements
[[ $# -lt 1 ]] && {
error 'Missing required argument to _htmlDecode_()!'
return 1
}
[[ $# -lt 1 ]] && {
error 'Missing required argument to _htmlDecode_()!'
return 1
}
local sedFile
sedFile="${HOME}/.sed/htmlDecode.sed"
local sedFile
sedFile="${HOME}/.sed/htmlDecode.sed"
[ -f "${sedFile}" ] \
&& { echo "${1}" | sed -f "${sedFile}"; } \
|| return 1
[ -f "${sedFile}" ] \
&& { echo "${1}" | sed -f "${sedFile}"; } \
|| return 1
}
_htmlEncode_() {
# DESC: Encode HTML characters with sed
# ARGS: $1 (Required) - String to be encoded
# OUTS: Prints output to STDOUT
# USAGE: _htmlEncode_ <string>
# NOTE: Must have a sed file containing replacements
# DESC: Encode HTML characters with sed
# ARGS: $1 (Required) - String to be encoded
# OUTS: Prints output to STDOUT
# USAGE: _htmlEncode_ <string>
# NOTE: Must have a sed file containing replacements
[[ $# -lt 1 ]] && {
error 'Missing required argument to _htmlEncode_()!'
return 1
error 'Missing required argument to _htmlEncode_()!'
return 1
}
local sedFile
sedFile="${HOME}/.sed/htmlEncode.sed"
local sedFile
sedFile="${HOME}/.sed/htmlEncode.sed"
[ -f "${sedFile}" ] \
&& { echo "${1}" | sed -f "${sedFile}"; } \
|| return 1
[ -f "${sedFile}" ] \
&& { echo "${1}" | sed -f "${sedFile}"; } \
|| return 1
}
_lower_() {
# DESC: Convert a string to lowercase
# ARGS: None
# OUTS: None
# USAGE: text=$(_lower_ <<<"$1")
# echo "STRING" | _lower_
tr '[:upper:]' '[:lower:]'
# DESC: Convert a string to lowercase
# ARGS: None
# OUTS: None
# USAGE: text=$(_lower_ <<<"$1")
# echo "STRING" | _lower_
tr '[:upper:]' '[:lower:]'
}
_upper_() {
# DESC: Convert a string to uppercase
# ARGS: None
# OUTS: None
# USAGE: text=$(_upper_ <<<"$1")
# echo "STRING" | _upper_
tr '[:lower:]' '[:upper:]'
# DESC: Convert a string to uppercase
# ARGS: None
# OUTS: None
# USAGE: text=$(_upper_ <<<"$1")
# echo "STRING" | _upper_
tr '[:lower:]' '[:upper:]'
}
_ltrim_() {
# DESC: Removes all leading whitespace (from the left)
# ARGS: None
# OUTS: None
# USAGE: text=$(_ltrim_ <<<"$1")
# echo "STRING" | _ltrim_
local char=${1:-[:space:]}
sed "s%^[${char//%/\\%}]*%%"
# DESC: Removes all leading whitespace (from the left)
# ARGS: None
# OUTS: None
# USAGE: text=$(_ltrim_ <<<"$1")
# echo "STRING" | _ltrim_
local char=${1:-[:space:]}
sed "s%^[${char//%/\\%}]*%%"
}
_regex_() {
# DESC: Use regex to validate and parse strings
# ARGS: $1 (Required) - Input String
# $2 (Required) - Regex pattern
# OUTS: Prints string matching regex
# Returns error if no part of string did not match regex
# USAGE: _regex_ "#FFFFFF" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
# NOTE: This example only prints the first matching group. When using multiple capture
# groups some modification is needed.
# https://github.com/dylanaraps/pure-bash-bible
if [[ $1 =~ $2 ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
return 0
else
return 1
fi
# DESC: Use regex to validate and parse strings
# ARGS: $1 (Required) - Input String
# $2 (Required) - Regex pattern
# OUTS: Prints string matching regex
# Returns error if no part of string did not match regex
# USAGE: _regex_ "#FFFFFF" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
# NOTE: This example only prints the first matching group. When using multiple capture
# groups some modification is needed.
# https://github.com/dylanaraps/pure-bash-bible
if [[ $1 =~ $2 ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
return 0
else
return 1
fi
}
_rtrim_() {
# DESC: Removes all leading whitespace (from the right)
# ARGS: None
# OUTS: None
# USAGE: text=$(_rtrim_ <<<"$1")
# echo "STRING" | _rtrim_
local char=${1:-[:space:]}
sed "s%[${char//%/\\%}]*$%%"
# DESC: Removes all leading whitespace (from the right)
# ARGS: None
# OUTS: None
# USAGE: text=$(_rtrim_ <<<"$1")
# echo "STRING" | _rtrim_
local char=${1:-[:space:]}
sed "s%[${char//%/\\%}]*$%%"
}
_trim_() {
# DESC: Removes all leading/trailing whitespace
# ARGS: None
# OUTS: None
# USAGE: text=$(_trim_ <<<"$1")
# echo "STRING" | _trim_
awk '{$1=$1;print}'
# DESC: Removes all leading/trailing whitespace
# ARGS: None
# OUTS: None
# USAGE: text=$(_trim_ <<<"$1")
# echo "STRING" | _trim_
awk '{$1=$1;print}'
}
_urlEncode_() {
# DESC: URL encode a string
# ARGS: $1 (Required) - String to be encoded
# OUTS: Prints output to STDOUT
# USAGE: _urlEncode_ <string>
# NOTE: https://gist.github.com/cdown/1163649
# DESC: URL encode a string
# ARGS: $1 (Required) - String to be encoded
# OUTS: Prints output to STDOUT
# USAGE: _urlEncode_ <string>
# NOTE: https://gist.github.com/cdown/1163649
[[ $# -lt 1 ]] && {
error 'Missing required argument to _urlEncode_()!'
return 1
}
[[ $# -lt 1 ]] && {
error 'Missing required argument to _urlEncode_()!'
return 1
}
local LANG=C
local i
local LANG=C
local i
for ((i = 0; i < ${#1}; i++)); do
if [[ ${1:$i:1} =~ ^[a-zA-Z0-9\.\~_-]$ ]]; then
printf "${1:$i:1}"
else
printf '%%%02X' "'${1:$i:1}"
fi
done
for ((i = 0; i < ${#1}; i++)); do
if [[ ${1:i:1} =~ ^[a-zA-Z0-9\.\~_-]$ ]]; then
printf "${1:i:1}"
else
printf '%%%02X' "'${1:i:1}"
fi
done
}
_urlDecode_() {
# DESC: Decode a URL encoded string
# ARGS: $1 (Required) - String to be decoded
# OUTS: Prints output to STDOUT
# USAGE: _urlDecode_ <string>
# DESC: Decode a URL encoded string
# ARGS: $1 (Required) - String to be decoded
# OUTS: Prints output to STDOUT
# USAGE: _urlDecode_ <string>
[[ $# -lt 1 ]] && {
error 'Missing required argument to _urlDecode_()!'
return 1
}
[[ $# -lt 1 ]] && {
error 'Missing required argument to _urlDecode_()!'
return 1
}
local url_encoded="${1//+/ }"
printf '%b' "${url_encoded//%/\\x}"
local url_encoded="${1//+/ }"
printf '%b' "${url_encoded//%/\\x}"
}