mirror of
https://github.com/natelandau/shell-scripting-templates.git
synced 2025-11-08 13:13:47 -05:00
Add new function and improve comments
This commit is contained in:
@@ -235,6 +235,7 @@ Functions for working with files.
|
||||
- **`_listFiles_`** Find files in a directory. Use either glob or regex.
|
||||
- **`_makeSymlink_`** Creates a symlink and backs up a file which may be overwritten by the new symlink. If the exact same symlink already exists, nothing is done.
|
||||
- **`_parseYAML_`** Convert a YAML file into BASH variables for use in a shell script
|
||||
- **`_printFileBetween_`** Prints block of text in a file between two regex patterns
|
||||
- **`_readFile_`** Prints each line of a file
|
||||
- **`_sourceFile_`** Source a file into a script
|
||||
- **`_createUniqueFilename_`** Ensure a file to be created has a unique filename to avoid overwriting other files
|
||||
|
||||
@@ -18,8 +18,6 @@ _mainScript_() {
|
||||
#/_mainsScript_()
|
||||
|
||||
# ################################## Flags and defaults
|
||||
# Script specific
|
||||
|
||||
# # Required variables
|
||||
LOGFILE="${HOME}/logs/$(basename "$0").log"
|
||||
QUIET=false
|
||||
@@ -29,6 +27,8 @@ FORCE=false
|
||||
DRYRUN=false
|
||||
declare -a ARGS=()
|
||||
|
||||
# Script specific
|
||||
|
||||
# ################################## Functions required for this template to work
|
||||
|
||||
_trapCleanup_() {
|
||||
|
||||
@@ -17,8 +17,6 @@ _mainScript_() {
|
||||
# end _mainScript_
|
||||
|
||||
# ################################## Flags and defaults
|
||||
# Script specific
|
||||
|
||||
# Required variables
|
||||
LOGFILE="${HOME}/logs/$(basename "$0").log"
|
||||
QUIET=false
|
||||
@@ -28,6 +26,8 @@ FORCE=false
|
||||
DRYRUN=false
|
||||
declare -a ARGS=()
|
||||
|
||||
# Script specific
|
||||
|
||||
# ################################## Custom utility functions (Pasted from repository)
|
||||
|
||||
# ################################## Functions required for this template to work
|
||||
|
||||
@@ -11,6 +11,8 @@ SOURCEFILE="${ROOTDIR}/utilities/files.bash"
|
||||
BASEHELPERS="${ROOTDIR}/utilities/misc.bash"
|
||||
ALERTS="${ROOTDIR}/utilities/alerts.bash"
|
||||
|
||||
PATH="/usr/local/opt/gnu-tar/libexec/gnubin:/usr/local/opt/coreutils/libexec/gnubin:/usr/local/opt/gnu-sed/libexec/gnubin:/usr/local/opt/grep/libexec/gnubin:${PATH}"
|
||||
|
||||
if test -f "${SOURCEFILE}" >&2; then
|
||||
source "${SOURCEFILE}"
|
||||
else
|
||||
@@ -68,6 +70,7 @@ teardown() {
|
||||
}
|
||||
|
||||
######## FIXTURES ########
|
||||
TEXT="${BATS_TEST_DIRNAME}/fixtures/text.txt"
|
||||
YAML1="${BATS_TEST_DIRNAME}/fixtures/yaml1.yaml"
|
||||
YAML1parse="${BATS_TEST_DIRNAME}/fixtures/yaml1.yaml.txt"
|
||||
unencrypted="${BATS_TEST_DIRNAME}/fixtures/test.md"
|
||||
@@ -433,6 +436,61 @@ _testParseYAML_() {
|
||||
assert_success
|
||||
}
|
||||
|
||||
@test "_printFileBetween_: match case-insensitive" {
|
||||
run _printFileBetween_ -i "^#+ orange1" "^#+$" "${TEXT}"
|
||||
assert_success
|
||||
assert_line --index 0 "############ Orange1 ############"
|
||||
assert_line --index 1 "# 1"
|
||||
assert_line --index 2 "# 2"
|
||||
assert_line --index 3 "# 3"
|
||||
assert_line --index 4 "# 4"
|
||||
assert_line --index 5 "#################################"
|
||||
refute_output --regexp "Grape|Orange2"
|
||||
}
|
||||
|
||||
@test "_printFileBetween_: match case-insensitive - greedy" {
|
||||
run _printFileBetween_ -ig "^#+ orange" "##" "${TEXT}"
|
||||
assert_success
|
||||
assert_line --index 0 "############ Orange1 ############"
|
||||
assert_line --index 1 "# 1"
|
||||
assert_line --index 2 "# 2"
|
||||
assert_line --index 3 "# 3"
|
||||
assert_line --index 4 "# 4"
|
||||
assert_line --index 5 "#################################"
|
||||
assert_line --index 6 "############ Orange2 ############"
|
||||
assert_line --index 7 "# 1"
|
||||
assert_line --index 8 "# 2"
|
||||
assert_line --index 9 "# 3"
|
||||
assert_line --index 10 "# 4"
|
||||
assert_line --index 11 "#################################"
|
||||
refute_output --regexp "Grape"
|
||||
}
|
||||
|
||||
@test "_printFileBetween_: no match" {
|
||||
run _printFileBetween_ "^#+ orange1" "^#+$" "${TEXT}"
|
||||
assert_failure
|
||||
}
|
||||
|
||||
@test "_printFileBetween_: remove lines" {
|
||||
run _printFileBetween_ -ri "^[A-Z0-9]+\(\)" "^ *}.*" "${TEXT}"
|
||||
assert_success
|
||||
assert_line --index 0 --partial "# buf : Backup file with time stamp"
|
||||
assert_line --index 5 --regexp "^ *cp -a .*"
|
||||
refute_output --regexp "buf\(\) {"
|
||||
refute_output --regexp '}[^"_]'
|
||||
refute_output --regexp "md5Check"
|
||||
}
|
||||
|
||||
@test "_printFileBetween_: remove lines - greedy" {
|
||||
run _printFileBetween_ -gr "^[a-zA-Z0-9]+\(\)" "^ *}.*" "${TEXT}"
|
||||
assert_success
|
||||
assert_line --index 0 --partial "# buf : Backup file with time stamp"
|
||||
assert_line --index 5 --regexp "^ *cp -a .*"
|
||||
refute_output --regexp "buf\(\) {"
|
||||
assert_line --index 29 --regexp "^ *fi.*"
|
||||
assert_output --regexp "md5Check"
|
||||
}
|
||||
|
||||
_testBackupFile_
|
||||
_testListFiles_
|
||||
_testMakeSymlink_
|
||||
|
||||
59
test/fixtures/text.txt
vendored
Normal file
59
test/fixtures/text.txt
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
############ Orange1 ############
|
||||
# 1
|
||||
# 2
|
||||
# 3
|
||||
# 4
|
||||
#################################
|
||||
|
||||
############ Orange2 ############
|
||||
# 1
|
||||
# 2
|
||||
# 3
|
||||
# 4
|
||||
#################################
|
||||
|
||||
############ Grape ############
|
||||
# 1
|
||||
# 2
|
||||
# 3
|
||||
# 4
|
||||
#################################
|
||||
|
||||
buf() {
|
||||
# buf : Backup file with time stamp
|
||||
local filename
|
||||
local filetime
|
||||
|
||||
filename="${1}"
|
||||
filetime=$(date +%Y%m%d_%H%M%S)
|
||||
cp -a "${filename}" "${filename}_${filetime}"
|
||||
}
|
||||
|
||||
md5Check() {
|
||||
# DESC: Compares an md5 hash to the md5 hash of a file
|
||||
# ARGS: None
|
||||
# OUTS: None
|
||||
# USAGE: md5Check <md5> <filename>
|
||||
|
||||
local opt
|
||||
local OPTIND=1
|
||||
local md5="$1"
|
||||
local file="$2"
|
||||
|
||||
if ! command -v md5sum &>/dev/null; then
|
||||
echo "Can not find 'md5sum' utility"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get md5 has of file
|
||||
local filemd5
|
||||
filemd5="$(md5sum "${file}")"
|
||||
|
||||
if [[ $filemd5 == "$md5" ]]; then
|
||||
success "The two md5 hashes match"
|
||||
return 0
|
||||
else
|
||||
warning "The two md5 hashes do not match"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -275,9 +275,9 @@ _columnizeOutput_() {
|
||||
# NOTE:
|
||||
# Long text or ANSI colors in the first column may create display issues
|
||||
# USAGE:
|
||||
# _columnizeOutput_ 0 30 10 "Key" "Long value text"
|
||||
# _columnizeOutput_ 0 30 "Key" "Long value text"
|
||||
|
||||
[[ $# -lt 5 ]] && fatal "Missing required argument to ${FUNCNAME[0]}"
|
||||
[[ $# -lt 4 ]] && fatal "Missing required argument to ${FUNCNAME[0]}"
|
||||
|
||||
local _leftIndent=$1
|
||||
local _leftColumn=$2
|
||||
|
||||
@@ -8,7 +8,7 @@ _dedupeArray_() {
|
||||
# OUTS:
|
||||
# stdout: Prints de-duped elements
|
||||
# USAGE:
|
||||
# _removeDups_ "${array[@]}"
|
||||
# mapfile -t newarray < <(_dedupeArray_ "${array[@]}")
|
||||
# NOTE:
|
||||
# List order may not stay the same
|
||||
# CREDIT:
|
||||
|
||||
@@ -58,7 +58,7 @@ _printArray_() {
|
||||
|
||||
[[ ${VERBOSE:-} != true ]] && return 0
|
||||
|
||||
debug "Printing contents of \${${_arrayName}[@]}" "${_lineNumber}"
|
||||
debug "Contents of \${${_arrayName}[@]}" "${_lineNumber}"
|
||||
|
||||
for _k in "${!_arr[@]}"; do
|
||||
debug "${_k} = ${_arr[${_k}]}"
|
||||
|
||||
@@ -671,6 +671,84 @@ _parseYAML_() {
|
||||
}' | sed 's/_=/+=/g' | sed 's/[[:space:]]*#.*"/"/g'
|
||||
}
|
||||
|
||||
_printFileBetween_() (
|
||||
# DESC:
|
||||
# Prints text of a file between two regex patterns
|
||||
# ARGS:
|
||||
# $1 (Required): Starting regex pattern
|
||||
# $2 (Required): Ending regex pattern
|
||||
# $3 (Required): Input string
|
||||
# OPTIONS:
|
||||
# -i (Optional) - Case-insensitive regex
|
||||
# -r (Optional) - Remove first and last lines (ie - the lines which matched the patterns)
|
||||
# -g (Optional) - Greedy regex (Defaults to non-greedy)
|
||||
# OUTS:
|
||||
# 0: Success
|
||||
# 1: Failure
|
||||
# stdout: Prints text between two regex patterns
|
||||
# USAGE:
|
||||
# _printFileBetween_ "^pattern1$" "^pattern2$" "String or variable containing a string"
|
||||
|
||||
[[ $# -lt 3 ]] && fatal "Missing required argument to ${FUNCNAME[0]}"
|
||||
|
||||
local _removeLines=false
|
||||
local _greedy=false
|
||||
local _caseInsensitive=false
|
||||
local opt
|
||||
local OPTIND=1
|
||||
while getopts ":iIrRgG" opt; do
|
||||
case ${opt} in
|
||||
i | I) _caseInsensitive=true ;;
|
||||
r | R) _removeLines=true ;;
|
||||
g | G) _greedy=true ;;
|
||||
*) fatal "Unrecognized option '${1}' passed to ${FUNCNAME[0]}. Exiting." ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
local _startRegex="${1}"
|
||||
local _endRegex="${2}"
|
||||
local _input="${3}"
|
||||
local _output
|
||||
|
||||
if [[ ${_removeLines} == true ]]; then
|
||||
if [[ ${_greedy} == true ]]; then
|
||||
if [[ ${_caseInsensitive} == true ]]; then
|
||||
_output="$(sed -nE "/${_startRegex}/I,/${_endRegex}/Ip" "${_input}" | sed -n '2,$p' | sed '$d')"
|
||||
else
|
||||
_output="$(sed -nE "/${_startRegex}/,/${_endRegex}/p" "${_input}" | sed -n '2,$p' | sed '$d')"
|
||||
fi
|
||||
else
|
||||
if [[ ${_caseInsensitive} == true ]]; then
|
||||
_output="$(sed -nE "/${_startRegex}/I,/${_endRegex}/I{p;/${_endRegex}/Iq}" "${_input}" | sed -n '2,$p' | sed '$d')"
|
||||
else
|
||||
_output="$(sed -nE "/${_startRegex}/,/${_endRegex}/{p;/${_endRegex}/q}" "${_input}" | sed -n '2,$p' | sed '$d')"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if [[ ${_greedy} == true ]]; then
|
||||
if [[ ${_caseInsensitive} == true ]]; then
|
||||
_output="$(sed -nE "/${_startRegex}/I,/${_endRegex}/Ip" "${_input}")"
|
||||
else
|
||||
_output="$(sed -nE "/${_startRegex}/,/${_endRegex}/p" "${_input}")"
|
||||
fi
|
||||
else
|
||||
if [[ ${_caseInsensitive} == true ]]; then
|
||||
_output="$(sed -nE "/${_startRegex}/I,/${_endRegex}/I{p;/${_endRegex}/Iq}" "${_input}")"
|
||||
else
|
||||
_output="$(sed -nE "/${_startRegex}/,/${_endRegex}/{p;/${_endRegex}/q}" "${_input}")"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n ${_output:-} ]]; then
|
||||
printf "%s\n" "${_output}"
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
)
|
||||
|
||||
_readFile_() {
|
||||
# DESC:
|
||||
# Prints each line of a file
|
||||
|
||||
@@ -243,7 +243,7 @@ _regexCapture_() {
|
||||
# 1 - Regex did not match
|
||||
# stdout: Prints string matching regex
|
||||
# USAGE:
|
||||
# HEXCODE=$(_regex_ "background-color: #FFFFFF;" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$')
|
||||
# HEXCODE=$(_regexCapture_ "background-color: #FFFFFF;" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$')
|
||||
# $ printf "%s\n" "${HEXCODE}"
|
||||
# $ #FFFFFF
|
||||
# NOTE:
|
||||
@@ -290,9 +290,9 @@ _rtrim_() {
|
||||
sed "s%[${_char//%/\\%}]*$%%"
|
||||
}
|
||||
|
||||
_splitString_() {
|
||||
_splitString_() (
|
||||
# DESC:
|
||||
# Splat a string into an array based on a given delimiter
|
||||
# Split a string into an array based on a given delimiter
|
||||
# ARGS:
|
||||
# $1 (Required) - String to be split
|
||||
# $2 (Required) - Delimiter
|
||||
@@ -302,15 +302,17 @@ _splitString_() {
|
||||
# stdout: Values split by delimiter separated by newline
|
||||
# USAGE:
|
||||
# ARRAY=( $(_splitString_ "string1,string2,string3" ",") )
|
||||
# CREDIT:
|
||||
# https://github.com/labbots/bash-utility/blob/master/src/misc.sh
|
||||
|
||||
[[ $# -lt 2 ]] && fatal "Missing required argument to ${FUNCNAME[0]}"
|
||||
|
||||
declare -a _arr=()
|
||||
IFS=$'\n' read -d "" -ra _arr <<<"${1//$2/$'\n'}"
|
||||
local _input="${1}"
|
||||
local _delimeter="${2}"
|
||||
|
||||
IFS="${_delimeter}" read -r -a _arr <<<"${_input}"
|
||||
|
||||
printf '%s\n' "${_arr[@]}"
|
||||
}
|
||||
)
|
||||
|
||||
_stringContains_() {
|
||||
# DESC:
|
||||
|
||||
Reference in New Issue
Block a user