Skip to content

Instantly share code, notes, and snippets.

@darkseid4nk
Last active December 12, 2024 05:50
Show Gist options
  • Save darkseid4nk/4de8a097ee981a207a3ba03e7ace6a14 to your computer and use it in GitHub Desktop.
Save darkseid4nk/4de8a097ee981a207a3ba03e7ace6a14 to your computer and use it in GitHub Desktop.
Helper functions for workin with arrays/dicts
# Most functions use direct referencing for dict compatibility and key referencing when indexes/keys may not be in a sequential numeric order.
# inarray is the only function that you expand the entire array as an argument i.e. "${_arr[@]}"
array_empty(){
# array_empty "_arrayname"
# uses direct reference
# Returns 0 if an array is empty. Returns 1 otherwise
# Works on arrays and dicts
[[ "$#" -ne "1" ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr=("${1}")
[[ -z "${_arr[@]}" ]] && return 0 || return 1
}
array_end(){
# array_end "_arrayname"
# uses direct reference
# Returns the value of the last element. Returns 1 if empty
# Works on arrays and dicts
[[ "$#" -ne "1" ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr="${1}"
[[ "${#_arr[@]}" -eq "0" ]] && return 1
local _keys=("${!_arr[@]}")
local _last_key="${_keys[-1]}"
printf "%s\n" "${_arr[$_last_key]}"
return 0
}
array_key_exists(){
# array_key_exists "key" "arrayordict_name"
# Uses direct reference. Cannot indirect reference dicts for keys.
# returns 0 if key exists in array. Otherwise returns 1. If array doesnt exist will return 1
# Works on arrays and dicts
[[ "$#" -ne "2" ]] && return 1
[[ "${!2@a}" != [aA] ]] && return 1
local _key="$1"
local -n _arr="$2"
[[ "${!_arr[@]}" =~ "${_key}"( |$) ]] && return 0 || return 1
}
array_key_first(){
# array_key_first <arrayordict_name>
# Uses direct reference. Cannot indirect reference dicts for keys.
# returns first key of array, otherwise returns 1 on empty
# Works on arrays and dicts
[[ "$#" -ne 1 ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr="$1"
local _keys=("${!_arr[@]}")
[[ -z "${_keys[0]}" ]] && return 1
printf "%s\n" "${_keys[0]}"
return 0
}
array_key_last(){
# array_key_last <arrayordict_name>
# Uses direct reference. Cannot indirect reference dicts for keys.
# returns last key of array, ootherwise returns 1
# Works on arrays and dicts
[[ "$#" -ne 1 ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr="$1"
local _keys=("${!_arr[@]}")
[[ "${#_keys[@]}" -eq 0 ]] && return 1
printf "%s\n" "${_keys[-1]}"
return 0
}
in_array(){
# in_array <needle> "${array_name[@]}"
# Expands entire array as function argument. Splits by |
# Searches for needle in haystack
# returns 0 if found, returns 1 otherwise.
# Works on arrays and dicts
joinByChar() { local IFS="$1"; shift; echo "$*"; }
shopt -s extglob
local element="$1"
shift
local array=("$@")
[[ "$element" == @($(joinByChar '|' "${array[@]//|/\\|}")) ]] && return 0 || return 1
}
array_pop(){
# array_pop <array_name>
# Uses direct reference to array
# pop element off the end of array
# returns the value of the last element of array, null if empty, returns 1 otherwise.
# Works on arrays and dicts
[[ "$#" -ne "1" ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr="$1"
local _keys=("${!_arr[@]}")
[[ "${#_keys[@]}" -eq 0 ]] && return 1
local _lastkey="${_keys[-1]}"
local _lastval="${_arr[$_lastkey]}"
unset _arr[${_lastkey}]
printf "%s\n" "${_lastval}"
return 0
}
array_push(){
# array_push <array_name> <string>
# push element onto the end of array
# Only works on arrays
[[ "$#" -ne "2" ]] && return 1
[[ "${!1@a}" != [a] ]] && return 1
local -n _arr="$1"
local _str="$2"
_arr[${#_arr[@]}]="${_str}"
return 0
}
array_search(){
# array_search <array_name> <string>
# Uses direct reference for compatibility with dicts.
# searches array for a given value and returns the first corresponding key if successful
# Otherwise return 1
# Works on arrays and dicts
[[ "$#" -ne "2" ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr="$1"
local _pattern="$2"
local key
for key in "${!_arr[@]}"; do
if [[ "${_arr[$key]}" =~ "$_pattern" ]]; then
printf "%s" "$key"
return 0
fi
done
return 1
}
array_shift(){
# array_shift <array_name>
# shift an element off the beginning of array
# returns the shifted value, or null if array is empty or is not an array
# Works on arrays and dicts
[[ "$#" -ne "1" ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr="$1"
local -a _keys=("${!_arr[@]}")
local _firstkey="${_keys[0]}"
[[ -z "${_firstkey}" ]] && return 1
local _firstvalue="${_arr[${_firstkey}]}"
unset _arr[$_firstkey]
printf "%s\n" "${_firstvalue}"
return 0
}
array_start(){
# array_start <array_name>
# Returns the value of the first element or false for empty array.
# Works on arrays and dicts
[[ "$#" -ne "1" ]] && return 1
[[ "${!1@a}" != [aA] ]] && return 1
local -n _arr="$1"
local -a _keys=("${!_arr[@]}")
local _firstkey="${_keys[0]}"
[[ -z "${_firstkey}" ]] && return 1
local _firstvalue="${_arr[${_firstkey}]}"
printf "%s\n" "${_firstvalue}"
return 0
}
array_unshift(){
# array_unshift <array_name> <string>
# pushes element onto the beginning of array
# Only works on arrays, not dicts.
[[ "$#" -ne "2" ]] && return 1
[[ "${!1@a}" != [a] ]] && return 1
local -n _arr="$1"
local _str="$2"
_arr=("${_str}" "${_arr[@]}")
return 0
}
array_strlen(){
# All 4 options are required to be passed.
# -m | mode=long or short, this will return the longest string or the shortest string
# -r | <string>. String name of array we are getting strlen from. This creates a reference to the array. (cant pass arrays in bash)
# -t | type=word or string. This defines whether we want to count the entire string value, or each word in each value (whitespace separation)
# -s | select=key or value. This defines whether we are getting the strlen the keys in the associative array, or the values
local -A _s
OPTIND=1
while getopts ":t:m:r:s:" opt; do
case ${opt} in
m) [[ "${OPTARG}" =~ ^(short)$|^(long)$ ]] && _s[m]="$(printf "sort -n%s" $([ -n "${BASH_REMATCH[2]}" ] && echo "r"))";;
r) local -n _ref="${OPTARG}" && [[ "${_ref@a}" =~ (A|a) ]] && _s[ref]=true;;
s) [[ "${OPTARG}" =~ ^(key|value)$ ]] && _s[s]="${OPTARG}";;
t) [[ "${OPTARG}" =~ ^(word|string)$ ]] && _s[t]="${OPTARG}";;
:) return 1;;
?) return 1;;
esac
done
[ "${#_s[@]}" -ne 4 ] && return 1
local -a _value_lengths
if [ "${_s[s]}" = "key" ] && [ "${_ref@a}" = "A" ]; then _iterate_arr=("${!_ref[@]}"); else _iterate_arr=("${_ref[@]}"); fi
[ "${_s[t]}" = "word" ] && IFS=$' ' || IFS=$'\n'
for str in ${_iterate_arr[@]}; do _value_lengths+=("${#str}"); done
IFS=$'\n' _array_val_largest=$(echo "${_value_lengths[*]}" | eval ${_s[m]} | head -n1)
echo "${_array_val_largest}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment