Last active
August 6, 2024 22:24
-
-
Save tie/7e81aaa4b357c486abc197bdbe00f27c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file is a library of Bash functions useful in practice for writing | |
# reliable scripts. | |
# | |
# References: | |
# • https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html | |
# These function accept variable names instead of their values to make misuse | |
# harder. In particular, $(…) expressions do not fail the script even if errexit | |
# is set. Instead of `printf '{"string":"%s"}' "$(escapeJSONString "$v")", write | |
# `escapeJSONString v && printf '{"string":"%s"}\n' "$v"` (or equivalent). | |
# Escape a string for use in JSON templates. | |
# See https://json.org | |
# | |
# Assumes that the current locale is compatible with Unicode. | |
# | |
# Example: | |
# $ bar='"hello world" | |
# \(^-^)/' | |
# $ escapeJSONString bar | |
# $ printf '{"text":"%s"}\n' "$bar" | |
function escapeJSONString() { | |
# TODO: implement "${!varName@J}" in Bash? | |
local varName=$1 | |
local in=${!varName} out= | |
local char | |
local -i charCode | |
while [[ -n $in ]]; do | |
char=${in:0:1} | |
in=${in:1} | |
case "$char" in | |
$'\b') out+='\b' ;; | |
$'\f') out+='\f' ;; | |
$'\n') out+='\n' ;; | |
$'\r') out+='\r' ;; | |
$'\t') out+='\t' ;; | |
\") out+='\"' ;; | |
\\) out+='\\' ;; | |
*) | |
printf -v charCode %d "'$char" | |
# Escape control characters as 4 hex digits. | |
if ((charCode < 0x20)); then | |
printf -v char \\u00%x $charCode | |
fi | |
out+=$char | |
;; | |
esac | |
done | |
printf -v "$varName" "%s" "$out" | |
} | |
# Prefix a value of the given variable name (first argument, required) if it | |
# starts with a string (second argument, defaults to “-”) with the third | |
# argument (defaults to “./”). | |
# | |
# Intended use case is to prefix paths for commands that do not implement a | |
# common convention of separating options and further arguments with "--". For | |
# example, `find`, `cc` and `echo`. | |
# | |
# Example: | |
# $ foo=-n | |
# $ prefixPath foo | |
# $ echo "$foo" | |
# ./-n | |
function prefixPath() { | |
local varName=$1 | |
local pattern=${2--} | |
local prefix=${3-./} | |
printf -v "$varName" "%s" "${!varName/#$pattern/"$prefix$pattern"}" | |
} | |
# Escape _replacement_ string for sed’s `s` command. | |
# See https://www.gnu.org/software/sed/manual/html_node/The-_0022s_0022-Command.html | |
# | |
# Fails if patsub_replacement shell option is not set. | |
# | |
# Usage: | |
# $ escapeSedReplacement foo : | |
# $ sed "s:foo:$foo" | |
# | |
# Example: | |
# $ bar='/usr/bin/\&bar' | |
# $ quoteSedReplacement bar | |
# $ echo "$bar" | |
# \/usr\/bin\/\\\&bar | |
function escapeSedReplacement() { | |
local varName=$1 | |
local sep=${2-/} | |
shopt -q patsub_replacement | |
printf -v "$varName" "%s" "${!varName//[$sep\\&$'\n']/\\&}" | |
} | |
# Checks whether file at the given path has executable file mode bit set. | |
# | |
# Example: | |
# $ isExecutableFile /bin/sh | |
function isExecutableFile() { | |
local fn=$1 | |
[[ -f $fn && -x $fn ]] | |
} | |
# Checks whether the given variable name is an indexed array. | |
# | |
# Example: | |
# $ declare -A var=(foo bar) | |
# $ isIndexedArray var | |
function isIndexedArray() { | |
local varName=$1 | |
[[ ${!varName@a} == *a* ]] | |
} | |
# Checks whether the given variable name is an associative array. | |
# | |
# Example: | |
# $ declare -A var=([foo]=bar [baz]=quux) | |
# $ isAssociativeArray var | |
function isAssociativeArray() { | |
local varName=$1 | |
[[ ${!varName@a} == *A* ]] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment