2

I want to print some logging style messages in my function, but also need to return a string value at the end of the function.

I came across namespaces but unfortunately I'm not working a recent enough version of bash.

For example:

doThing() {
   echo "stuff"
   echo "things"
   echo "usefulstring"
}

result=$( doThing )

[[ $result = "usefulstring" ]] && echo "Worked" || echo "Failed. :("

I would really rather avoid globals, and from what I've read I should avoid eval. So what other options are there?

Also - I would like to see the logging echos on stdout, but not the return value. Is it possible to use redirection within the function to achive this?

Jordan Mackie
  • 2,264
  • 4
  • 25
  • 45

3 Answers3

2

You can use an array and get the last element:

doThing() {
   echo "stuff"
   echo "things"
   echo "usefulstring"
}

# This creates an array
result=($( doThing ))
echo ${result[@]}    # Just for debugging

# This get the index of the last element
end=$(( ${#result[*]} - 1 ))
result=${result[$end]}

echo $result    # Just for debugging

[[ $result = "usefulstring" ]] && echo "Worked" || echo "Failed. :("

Gives:

stuff things usefulstring
usefulstring
Worked
cdarke
  • 42,728
  • 8
  • 80
  • 84
1

Assuming if you are OK with a minimal disk I/O, you could open a file descriptor to write to a file and then later parse it once the function is complete.

In this example, fd 3 will serve our purpose

doThing() {
   echo "stuff"
   echo "things"

   exec 3<> /tmp/foo
   echo "usefulstring" >&3
   exec 3>&-
}

and now parse this file using read for a single variable or mapfile if you are passing multiple words to the array. This way, the variable holds the string values even if they contain spaces between.

doThing
read -r str < /tmp/foo

The result would be available in str which you can quote it in conditionals. If your file system keeps /tmp or /var busy, you could use mktemp to create a file on your local directory to use for the fd.

This also satisfies your last requirement - I would like to see the logging echos on stdout, but not the return value.

Inian
  • 80,270
  • 14
  • 142
  • 161
1

In general, logging-type output from a program (or shell function) that's distinct from its primary output data should be sent to standard error rather than standard output, something like this:

doThing() {
   echo "stuff" >&2    # Logging output goes to stderr
   echo "things"  >&2
   echo "usefulstring"
}

...then result=$( doThing ) will print "stuff" and "things" to stderr, and set result to "usefulstring". If you want the logging output to wind up going to the script's standard output, you can redirect it back like this:

result=$( doThing ) 2>&1
Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151