useful bash scripting functions
Over time I've found various techniques and tactics that can be useful when scripting away so figured I'd share some of them here for documentation sake.
I have a bit of an obsession with bash scripting, to the extent that I've probably read thru the entire man page several times over by now. I've been bash scripting since I was a kid but I really started getting into it in my professional careers as well as at home in my lab. Over time I've found various techniques and tactics that can be useful when scripting away so figured I'd share some of them here for documentation sake.
printf
This first ones are pretty simple: printing text. I like to use printf
over echo
due to the ability to specify a format and have just a little more power over what you're writing to the terminal.
function :printf () {
builtin printf -- "$1" "${@:2}"
}
- The
--
is used to ensure the format isn't accidentally interpreted asprintf
options builtin
isn't required if the function name is something other thanprintf
otherwise recursion would (likely?) ensue.
Usage:
:printf '%s, %s!\n' 'Hello' 'World'
# Hello, World!
To build on this printf
helper function I like to include a couple additional functions:
vprintf
printfln
vprintfln
print
vprint
println
vprintln
define
This next one is a slightly more complex way to assign a variable value using the read
builtin and shell redirections, such as a heredoc, and while preserving whitespace. This can be very useful, especially if you want to use a subshell redirection for some fancy programmatic value building: :define VAR_NAME <(some_script)
.
function :define () {
IFS=$'\n' read -r -d '' "$@" || true
}
IFS=$'\n'
- Sets the Internal Field Separator to a newline character (used for word splitting)-r
- "Do not allow backslashes to escape any characters" (See:help read
)-d ''
- "Continue until the first character of DELIM is read, rather than newline" (See:help read
) This ensuresread
consumes all ofstdin
|| true
- Ensuresread
doesn't hang since it will exit with a non-zero return code when the end of the file is encountered
Usage:
:define SAMPLE_VAR <<'EOD'
This is a sample document.
Leading whitespace is preserved.
EOD
declare -p SAMPLE_VAR
# declare -- SAMPLE_VAR="This is a sample document.
# Leading whitespace is preserved."
readline
This last one is just a simple but useful helper for while loops and reading line by line into a variable while preserving whitespace.
function :readline () {
IFS= read -r "$@"
}
IFS=
- Sets the Internal Field Separator blank so the whole line is captured-r
- "Do not allow backslashes to escape any characters" (See:help read
)
Note: Even though only one variable name works here, we use "$@"
instead of just "$1"
incase any additional read
options are desired.
Usage:
while :readline line
do
declare -p line
done <<'EOD'
Hello,
World!
EOD
# declare -- line="Hello,"
# declare -- line=" World!"
Well, hopefully there's something of value here for someone. I know these are pretty simple and straightforward if you're already familiar with bash scripting, but I like to establish a little bit of a bootstrap like this before writing out my scripts. Let me know in the comments if you have any questions or know of anything I missed or got wrong, or any other neat techniques for bashing! Happy scripting
Discussion