summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-01-08 09:20:50 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-01-08 09:20:50 +0200
commit1847b5ba3d51020c44ba2388533a1a5427feadb1 (patch)
tree28f40426102f4dfdc383b904c5ae6b5a2787dc15
parent6dd41689e4ff9cd70eb9b7073a6b28b427980ce3 (diff)
Describe multi-value return technique in Bash style guide
-rw-r--r--doc/bash-style.cli91
1 files changed, 88 insertions, 3 deletions
diff --git a/doc/bash-style.cli b/doc/bash-style.cli
index 1b32b1a..17a850d 100644
--- a/doc/bash-style.cli
+++ b/doc/bash-style.cli
@@ -577,10 +577,95 @@ function dist()
}
\
+A function can return data in two primary ways: exit code and stdout.
+Normally, exit code 0 means success and exit code 1 means failure though
+additional codes can be used to distinguish between different kinds of
+failures, signify special conditions, etc., see \l{#error-handing Error
+Handling} for details.
+
+A function can also write to stdout with the result available to the caller in
+the same way as from programs (command substitution, pipeline, etc). If a
+function needs to return multiple values, then it can print them separated
+with newlines with the caller using the \c{readarray} builtin to read them
+into an indexed array, for example:
+
+\
+function foo ()
+{
+ echo one
+ echo two
+ echo three
+}
+
+foo | readarray -t r
+\
+
+In this case, if the function can fail, then the failure should be explicitly
+checked for (either by examining \c{PIPESTATUS} or via the lack of the
+result), since the error trap will not be triggered (unless the \c{pipefail}
+shell option is set; see \l{#error-handing Error Handling} for details). For
+example:
+
+\
+foo | readarray -t r
+
+if [ \"${PIPESTATUS[0]}\" -ne 0 ]; then
+ exit 1
+fi
+\
+
+\N|The use of the newline as a separator means that values may not contain
+newlines. While \c{readarray} supports specifying a custom separator with the
+\c{-d} option, including a \c{NUL} separator, this support is only available
+since Bash 4.4.|
+
+This technique can also be extended to return an associative array by
+returning the values as an indexed array and then converting them to
+an associative array with \c{eval}, for example:
+
+\
+function foo ()
+{
+ echo \"[a]=one\"
+ echo \"[b]=two\"
+ echo \"[c]=three\"
+}
+
+foo | readarray -t ia
+
+if [ \"${PIPESTATUS[0]}\" -ne 0 ]; then
+ exit 1
+fi
+
+eval declare -A aa=(\"${ia[@]}\")
+\
+
+Note that if a key or a value contains whitespaces, then it must be quoted.
+The recommendation is to always quote both, for example:
+
+\
+function foo ()
+{
+ echo \"['a']='one ONE'\"
+ echo \"['b']='two'\"
+ echo \"['c']='three'\"
+}
+\
+
+Or, if returning a local array:
+
+\
+function foo ()
+{
+ declare -A a=([a]='one ONE' [b]=two [c]=three)
+
+ for k in \"${!a[@]}\"; do
+ echo \"['$k']='${a[$k]}'\"
+ done
+}
+\
+
For more information on returning data from functions, see
\l{https://mywiki.wooledge.org/BashFAQ/084 BashFAQ#084}.
-For more information on writing reusable functions, see
-\l{https://stackoverflow.com/questions/11369522/bash-utility-script-library
-Bash Utility Script Library}.
"