add modules from scripting subdirectory

master
Kebler Network System Administrator 2022-04-06 12:27:26 -07:00
parent ef8afa39c7
commit 1778ddca3e
9 changed files with 408 additions and 9 deletions

218
modules/scripting/array.mod Normal file
View File

@ -0,0 +1,218 @@
#!/bin/bash
#
# Author: Hugo Thunnissen <hugo.thunnissen@gmail.com>
# License: see LICENSE file.
#
##
# Utility functions for common array operations.
# To prevent circular references, none of the functions allow
# usage on an array named "array", and some won't allow the usage
# of an array by the name "oth_array" for a second arrayname that is passed.
# Functions that do variable assignment won't allow the usage of a variable
# by the name "variable".
#
##
## IMPPORTANT: CANNOT DO THIS IN A SUBSHELL i.e. $( )
##
# Check if an array is eligible to use the functions on.
# return values:
# 1: Array variable has not been set.
# 2: The array variable is named "array"
#
# array, string, delimiter
function String::split() {
#!/bin/bash
Array::isValid "$1" || return $?
[[ $2 ]] || return 1
delimiter=${3:-" "}
s=$2$delimiter
# echo del: $delimiter
# echo string: $s
declare -n array="$1"
while [[ $s ]]; do
array+=( "${s%%"$delimiter"*}" );
# echo added element now: ${array[@]}
s=${s#*"$delimiter"};
# echo remains: $s
done;
}
function Array::isValid() {
if ! declare -p "$1" &>>/dev/null; then
echo 'Array: Array variable needs to be set.' >&2
return 1
elif [[ $1 == array ]]; then
echo 'Array: Array variable can not be named "array"' >&2
return 2
fi
}
##
# Check if a variable can be assigned.
# return values:
# 3: The variable has not yet been declared
# 5: The variable is named "variable"
#
# $1 variable_name
function Array::varIsValid() {
if ! [[ -v $1 ]]; then
echo 'Array: Variable needs to be declared before assigning to it.' >&2
return 3
elif [[ $1 == variable ]]; then
echo 'Array: Variable cannot be named "variable"' >&2
return 5
fi
}
##
# pop an array
# return values:
# 4: array size is 0
# other: see Array::isValid
#
# $1: array_name
function Array::pop() {
Array::isValid "$1" || return $?
declare -n array="$1"
[[ ${#array[@]} -gt 0 ]] || return 4
unset 'array[-1]'
}
##
# Pop an array and assign the popped value to a variable
# return values:
# 4: array size is 0
# other: see Array::isValid and Array::varIsValid
#
# $1: array_name
# $2: variable_name
function Array::popToVar() {
Array::isValid "$1" || return $?
Array::varIsValid "$2" || return $?
declare -n array="$1" variable="$2"
[[ ${#array[@]} -gt 0 ]] || return 4
variable="${array[-1]}"
Array::pop "$1"
}
##
# Shift an array.
# $1: array_name
function Array::shift() {
Array::isValid "$1" || return $?
declare -n array="$1"
declare -i shift_amount="$2"
((shift_amount = shift_amount == 0 ? ++shift_amount : shift_amount))
[[ ${#array[@]} -gt 0 ]] || return 4
set -- "${array[@]}"
shift $shift_amount
array=("$@")
}
##
# Shift an array and assign the shifted value to a variable
# $1: array_name
# $2: variable_name
function Array::shiftToVar() {
Array::isValid "$1" || return $?
Array::varIsValid "$2" || return $?
# TODO: Add shifting to multiple variables
declare -n array="$1" variable="$2"
[[ ${#array[@]} -gt 0 ]] || return 4
variable="${array[0]}"
Array::shift "$1"
}
##
# Push a value to an array
# $1: array_name
# $2: value
function Array::push() {
Array::isValid "$1" || return $?
declare -n array="$1"
shift
array=("${array[@]}" "$@")
}
##
# Unshift a value to an array
# $1: array_name
# $*: values
function Array::unshift() {
Array::isValid "$1" || return $?
declare -n array="$1"
shift
array=("$@" "${array[@]}")
}
##
# Map through an array with a callback and assign the yielded values
# to the defined array.
# $1: array_name
# $2: array_to_be_assigned_to_name (may not be "oth_array")
# $3: callback_name
function Array::map() {
if ! declare -F "$3" &>>/dev/null; then
echo 'Array: Error, $3 for Array::map must be a function name'
return 6
fi
Array::isValid "$1" || return $?
Array::isValid "$2" || return $?
declare -n array="$1"
declare -a oth_array=()
declare func="$3" in_Array_map="true"
for item in "${array[@]}"; do
"$func" "$item"
done
declare -n array="$2"
array=("${oth_array[@]}")
}
##
# Strictly for use in Array::map callbacks.
# $1: Variable that should be added to the new array
function Array::yield() {
[[ "$in_Array_map" == true ]] && oth_array=("${oth_array[@]}" "$@")
}
##
# Check if an array has a certain value stored in it.
# $1: arrayname
# $2: value
function Array::hasValue() {
if ! Array::isValid "$1"; then
echo "$(caller): $1 is not a valid array."
exit 1
fi
declare -n array="$1"
if [[ $2 == +([0-9]) ]]; then
for item in "${array[@]}"; do
[[ $2 -eq $item ]] && return 0
done
else
for item in "${array[@]}"; do
[[ "$2" == "$item" ]] && return 0
done
fi
return 1
}

View File

@ -1,10 +1,7 @@
#!/bin/bash
# ====================================================================== # ======================================================================
# #
# @link http://wuhrr.wordpress.com/2010/01/13/adding-confirmation-to-bash/#comment-3540 # flags: -s, use strong confirmation, only yes or YES or Yes is accepted
#
# Function: confirm
# Asks the user to confirm an action, If the user does not answer yes,
# then the script will immediately exit.
# #
# Parameters: # Parameters:
# $@ - The confirmation message # $@ - The confirmation message
@ -13,6 +10,10 @@
# > # Example 1 # > # Example 1
# > # The preferred way to use confirm # > # The preferred way to use confirm
# > confirm Delete file1? && echo rm file1 # > confirm Delete file1? && echo rm file1
# > or
# > [[ confirm Delete file1 ]]; then
# > rm file1
# > fi
# > # >
# > # Example 2 # > # Example 2
# > # Use the $? variable to examine confirm's return value # > # Use the $? variable to examine confirm's return value
@ -32,9 +33,12 @@
function confirm() function confirm()
{ {
echo -n "$@ " local res="y Y yes YES Yes Sure sure SURE OK ok Ok"
local strong="yes YES Yes"
[[ $1 = "-s" ]] && { res=$strong; strong=true shift; } || strong=""
echo -n "$@" "$([[ $strong ]] && echo \< $res \>) ? "
read -e answer read -e answer
for response in y Y yes YES Yes Sure sure SURE OK ok Ok for response in $res
do do
if [ "_$answer" == "_$response" ] if [ "_$answer" == "_$response" ]
then then

View File

@ -0,0 +1,62 @@
#!/bin/bash
# must be json as a string, depends on jq
get_prop_value () {
local value
# echo in $1 get $2
value=$(echo $1 | jq -r .$2)
echo $value
}
is_array() {
local variable_name=$1
[[ "$(declare -p $variable_name 2>/dev/null)" =~ "declare -a" ]]
}
filename() {
# passed entire path
echo $(basename "$1" | rev | cut -f 2- -d '.' | rev)
}
# // TODO remove and use path module
# // must change acl.lib and loginout, chromium, and ungoogled install files
adirname() {
# passed entire path
echo "$(cd "$(dirname "$1")" >/dev/null 2>&1 ; pwd -P )"
}
user_exists() {
id -u $1 > /dev/null 2>&1
[[ $? == 1 ]] || echo $1
}
chmod_dirs() {
# passed entire path
local usesudo
[[ $1 == -s ]] && usesudo="sudo" && shift 2
$usesudo find $1 -type f -exec chmod $2 {} +
}
parse_option () {
# usage: parse_option -f "-b one -p 22 -F another" -p
# if -f is used then it will return the complete option
# otherwise just the options value
local opts;local f;local opt; local ret
[[ $1 = "-f" ]] && { f=true;shift 1; }
[[ $1 && $2 ]] || return 1
opts=$1
opt=$2
[[ ! $opts =~ "$opt" ]] && return 1
ret=$(sed -n "/^.*$opt\s\+\(\w\+\).*$/s//\1/p" <<< $opts)
[[ $f ]] && echo "$2 $ret" || echo $ret
}
remove_end_spaces () {
del=${2:-\'}
# echo delimiter: $del
# sed -e "s/[[:space:]]\{1,\}$del/$del/" <<< "$1"
res=$(sed -e "s/^$del[[:space:]]*/$del/" <<< "$1")
# echo leading: $res
sed -e "s/[[:space:]]*${del}$/$del/" <<< "$res"
}

View File

@ -0,0 +1,45 @@
#!/bin/bash
minimize () {
# will minimize script, removing comment lines and blank lines and inline comments
# TODO -r remove shebang, replace newlines with ; remove continuation \
# usage: <options> "source" (source as text or source as filename, as text MUST be quoted!)
# options:
# -t # argment will get text of source, otherwise it is the file path
# -o filepath # output to file
# -v # verbose, only applies when using -o. will output to file and return (stdout).
local out; local verbose; local text
local min="/^[[:space:]]*#/d; /#$/d; /^$/d; s/\(.*\)#.*/\1/"
local OPTION; local OPTARG; local OPTIND
# host=$(sed 's/\(.*\):.*/\1/' <<<"$SRC")
while getopts 'to:v' OPTION; do
# echo $OPTION $OPTARG
case "$OPTION" in
t)
text=true
;;
v)
verbose=true
;;
o)
out="$OPTARG"
;;
*)
echo unknown option $OPTION
;;
esac
done
shift $((OPTIND - 1))
if [[ $text ]]; then
res="$(echo "$1" | sed "$min")"
else
res="$(sed "$min" "$1")"
fi
if [[ $out ]]; then
[[ $verbose ]] && echo "$res" | tee "$out" || echo "$res" > "$out"
else
echo "$res"
fi
}

41
modules/scripting/path.sh Normal file
View File

@ -0,0 +1,41 @@
#!/bin/bash
isAbsPath() {
if [[ "${1:0:1}" == / || "${1:0:2}" == ~[/a-z] ]]
then
echo "true"
return 0
else
return 1
fi
}
# get full absolute path from a current or parent path
function abs_path {
local target="$1"
[[ $(isAbsPath $target) ]] && { echo $target; return 0; }
# echo relative path finding absolute
if [[ ! $(echo "$target" | sed 's/^\.\..*//') ]]; then
# echo .. parent directory
echo "$(dirname "$(pwd)")/${target/..//}" | tr -s /
return 0
fi
if [[ ! $(echo "$target" | sed 's/^\..*//') ]]; then
# echo . current directory
echo "$(pwd)/${target/.//}" | tr -s /
return 0
fi
# echo simple relative
echo "$(pwd)/$target" | tr -s /
}
# get full absolute path from a current or parent path
function abs_dir {
# with no trailing / will assume that is a file
# and remove it so return only the directory.
local target="$1"
[[ ! "$target" == */ ]] && target=$(dirname $target)
echo $(abs_path $target)
}

View File

@ -2,6 +2,9 @@
# echo loading yaml module # echo loading yaml module
# https://gist.github.com/pkuczynski/8665367 # https://gist.github.com/pkuczynski/8665367
# read yaml file, second argument (if any) is added prefix # read yaml file, second argument (if any) is added prefix
module_load minimize
parse_yaml() { parse_yaml() {
local prefix=$2 local prefix=$2
local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
@ -19,7 +22,17 @@ parse_yaml() {
} }
yaml() { yaml() {
python3 -c "import yaml;print(yaml.safe_load(open('$1'))$2)" dic=$(parse_yaml $1)
echo $dic
declare -A test
while read -d, -r pair; do
IFS='=' read -r key val <<<"$pair"
echo adding $val to $key
test[$key]=$val
done <<<"$dic\n"
echo ${test['MP']}
echo ${test[@]}
} }
# dic=$(python3 -c "import yaml;print(yaml.safe_load(open('$1')))")

View File

@ -0,0 +1,16 @@
#!/bin/bash
iecho () {
[[ ! -z "$PS1" ]] && echo $1
}
# no way to tell if sourced vs subshell
# # [[ ! -z "$PS1" ]] && [[ $SHLVL -eq 1 ]] && echo $1
# # echo [[ -z $PS1 ]]
# echo $SHLVL
# echo $$
# echo $BASHPID
# if [[ -t 1 ]]; then
# echo "Terminal"
# else
# echo "Not-a-terminal"
# fi