barefly
barefly

Reputation: 378

returning values in a bash function

I'm working with a growing bash script and within this script I have a number of functions. One of these functions is supposed to return a variables value, but I am running into some issues with the syntax. Below is an example of the code.

ShowTags() {
    local tag=0
    read tag
    echo "$tag"
}

selected_tag=$(ShowTags)
echo "$selected_tag"

pulled this code from a Linux Journal article, but the problem is it doesn't seem to work, or perhaps it does and im missing something. Essentially whenever the function is called the script hangs up and does not output anything, I need to CTRL+C to drop back to CLI.

The article in question is below.

http://www.linuxjournal.com/content/return-values-bash-functions

So my question is this the proper way to return a value? Is there a better or more dependable way of doing this? And if there is please give me an example so I can figure this out without using global variables.

EDIT:

The behavior of this is really getting to me now. I am using the following script.

ShowTags() {  

     echo "hi"
     local tag=0
     read tag
     echo "$tag"
}            

selected_tag=$(ShowTags)
echo "$selected_tag

Basically what happens is bash will act as if the read command is taking place before the echo tag at the top of the function. As soon as I pass something to read though it will run the top echo, and complete the rest of the script. I am not sure why this is happening. This is exactly what is happening in my main script.

Upvotes: 2

Views: 222

Answers (3)

Barmar
Barmar

Reputation: 780723

Change echo "hi" to echo "hi" >/dev/tty.

The reason you're not seeing it immediately is that $(ShowTags) captures all the standard output of the function, and that gets assigned to selected_tag. So you don't see any of it until you echo that variable.

By redirecting the prompt to /dev/tty, it's always displayed immediately on the terminal, not sent to the function's stdout, so it doesn't get captured by the command substitution.

Upvotes: 2

Gordon Davisson
Gordon Davisson

Reputation: 125708

As @thatotherguy pointed out, your function declaration syntax is off; but I suspect that's a transcription error, as if it was wrong in the script you'd get different problems. I think what's going on is that the read tag command in the function is trying to read a value from standard input (by default that's the terminal), and pausing until you type something in. I'm not sure what it's intended to do, but as written I'd expect it to pause indefinitely until something's typed in.

Solution: either type something in, or use something other than read. You could also add a prompt (read -p "Enter a tag: " tag) to make it more clear what's going on.

BTW, I have a couple of objections to the linux journal article you linked. These aren't relevant to your script, but things you should be aware of.

First, the function keyword is a nonstandard bashism, and I recommend against using it. myfunc() ... is sufficient to introduce a function definition.

Second, and more serious, the article recommends using eval in an unsafe way. Actually, it's really hard to use eval safely (see BashFAQ #48). You can improve it a great deal just by changing the quoting, and even more by not using eval at all:

eval $__resultvar="'$myresult'"    # BAD, can evaluate parts of $myresult as executable code
eval $__resultvar='"$myresult"'    # better, is only vulnerable to executing $__resultvar
declare $__resultvar="$myresult"   # better still

See BashFAQ #6 for more options and discussion.

Upvotes: 0

that other guy
that other guy

Reputation: 123410

You are trying to define a function with Name { ... ]. You have to use name() { ... }:

ShowTags() {    # add ()
local tag=0
read tag
echo "$tag"
}               # End with }

selected_tag=$(ShowTags)
echo "$selected_tag"

It now lets the user type in a string and have it written back:

$ bash myscript 
hello world     # <- my input
hello world     # script's output

You can add a prompt with read -p "Enter tag: " tag to make it more obvious when to write your input.

Upvotes: 0

Related Questions