Reputation: 1926
In my program I am trying to return a value from a function, the return value is string. Everything works fine(atleast some part), if I echo the value once it is returned, but it is not even calling the function, if I dont return.... Consider the code below....
#!/bin/bash
function get_last_name() {
echo "Get Last Name"
ipath=$1
IFS='/'
set $ipath
for item
do
last=$item
done
echo $last
}
main() {
path='/var/lib/iscsi/ifaces/iface0'
current=$(get_last_name "$path")
echo -n "Current="
echo $current
}
main
It gives me an output like this
OUTPUT
Current=Get Last Name iface0
If I comment the echo $current, then the I am not even seeing the "Get Last Name", which makes to come to conclusion, that it is not even calling the function. Please let me know what mistake I am making. But one thing I am sure, bash is the ugliest language I have ever seen.......
Upvotes: 2
Views: 6421
Reputation: 532368
Functions do not have return values in bash. When you write
current=$(get_last_name "$path")
you are not assigning a return value to current
. You are capturing the standard output of get_last_name
(written using the echo
command) and assigning it to current
. That's why you don't see "Get last name"; that text does not make it to the terminal, but is stored in current
.
Let's walk through get_last_name
first (with some slight modifications to simplify the explanation):
function get_last_name () {
ipath=$1
local IFS='/'
set $ipath
for item
do
last=$item
done
echo "Get Last Name"
echo $last
}
I added the local
command before IFS
so that the change is confined to the body of get_last_name
, and I moved the first echo
to the end to emphasize the similarity between the two echo
statements. When get_last_name
is called, it processes its single argument (a string containing a file path), then echoes two strings: "Get Last Name" and the final component of the file path. If you were to run execute this function from the command line, it would appear something like this:
$ get_last_name /foo/bar/baz
Get Last Name
baz
The exit code of the function would be the exit code of the last command executed, in this case echo $last
. This will be 0 as long as the write succeeds (which it almost certainly will).
Now, we look at the function main
, which calls get_last_name
:
main() {
path='/var/lib/iscsi/ifaces/iface0'
current=$(get_last_name "$path")
echo -n "Current="
echo $current
}
Just like with get_last_name
, main
will not have a return value; it will produce an exit code which is the exit code of echo $current
. The function begins by calling get_last_name
inside a command substitution ($(...)
), which will capture all the standard output from get_last_name
and treat it as a string.
DIGRESSION
Note the difference between the following:
current=$(get_last_name "$path")
sets the value of current
to the accumulated standard output of get_last_name
. (Among other things, newlines in the output are replaced with spaces, but the full explanation of how whitespace is handled is a topic for another day). This has nothing to do with return values; remember, the exit code (the closet thing bash
has to "return values") is a single integer.
current=get_last_name "$path"
would not even call get_last_name
. It would interpret "$path" as the name of a command and try to execute it. That command would have a variable current
with the string value "get_last_name" in its environment.
The point being, get_last_name
doesn't "return" anything that you can assign to a variable. It has an exit code, and it can write to standard output. The $(...)
construct lets you capture that output as a string, which you can then (among other things) assign to a variable.
Back to main
Once the value of current
is set to the output generated by get_last_name
, we execute
two last echo
statements to write to standard output again. The first writes "Current=" without a newline, so that the next echo
statement produces text on the same line as the first. The second just echoes the value of current
.
When you commented out the last echo
of main
, you didn't stop get_last_name
from being executed (it had already been executed). Rather, you just didn't print the contents of the current
variable, where the output of get_last_name
was placed rather than on the terminal.
Upvotes: 8