Some functions have a _var
variant; for example, two functions exists to extract the filename
extension:
mbfl_file_extension mbfl_file_extension_var
the first variant will print the result to stdout
, while the _var
variant will store the
result in a “result variable” whose name is handed to it as first argument; this mechanism is
built using the local -n
feature of Bash. The _var
variants are often a bit faster
because many output variants are wrappers for the _var
variants.
Basic API usage example:
mbfl_file_extension /path/to/file.ext -| ext local _RV mbfl_file_extension_var _RV /path/to/file.ext "$_RV" ⇒ ext
read below to understand why we should use the preprocessor and write the code like this:
mbfl_declare_varref(RV) mbfl_file_extension_var mbfl_datavar(RV) /path/to/file.ext "$RV" ⇒ ext
We must be careful when using this feature! Let’s consider this script:
function main () { local -i X=0 mbfl_func X echo X=$X >&2 } function mbfl_func () { local -n Y=${1:?} Y=1 } main
everything is fine: the script will print X=1
because the call to mbfl_func
will
mutate the variable X
in its execution environment, and such variable happens to be defined
in the scope of main
.
Now let’s consider this script:
function main () { local -i X=0 mbfl_func X echo X=$X >&2 } function mbfl_func () { local -n Y=${1:?} local X Y=1 } main
it will print X=0
because mbfl_func
accesses the variable X
in its execution
environment, and such variable is defined by mbfl_func
itself; the local definition of
X
shadows the upper level definition.
There is no true escape from this problem! There is no definitive way to avoid “fishing” a local
variable in a lower function from an upper function. MBFL attempts to mitigate the problem by
prefixing its variables with mbfl_
when a function uses reference variables. We should also
prefix our “result variables”, for example with a leading or trailing underscore: MBFL never
uses such a prefix or suffix.
So we should write the script as follows:
function main () { local -i _X=0 mbfl_func _X echo _X=$_X >&2 } function mbfl_func () { local -n mbfl_Y=${1:?} local mbfl_X mbfl_Y=1 } main
MBFL’s preprocessor has facilities to help us create variables with unique names that we can safely use as argument to functions, Using the script preprocessor.
With these facilities, the first example should be written as:
mbfl_declare_varref(RV) mbfl_file_extension_var mbfl_datavar(RV) /path/to/file.ext "$RV" ⇒ ext
and the demo script as:
function main () { mbfl_declare_integer_varref(X, 0) mbfl_func mbfl_datavar(X) echo X=$X >&2 } function mbfl_func () { mbfl_mandatory_nameref_parameter(Y, 1, the result variable) Y=1 } main
Using such preprocessor facilities consumes some computation time; they should be used when we do not care about execution time and when such time is significantly less than running a subshell. Otherwise we should just run the functions in a subshell:
RESULT=$(mbfl_file_extension /path/to/file.ext) "$RESULT" ⇒ ext
This document describes version 3.0.0-devel.9 of Marcos Bash Functions Library.