How to return a string value from a Bash function
There is no better way I know of. Bash knows only status codes (integers) and strings written to the stdout.
Bash: Return a string from bash function
The return
statement used by bash
is used to return a numeric value as a status code to be retrieved through $?
by the calling function. You can not return a string. See also
- Returning Values from Bash Functions
- How to return a string value from a Bash function
You can either use a special global variable as proposed by @konsolebox, or echo
the return value inside your function, and use command substitution when calling the function:
makeName()
{
echo "$fileName.$1.log"
}
echo -n "Enter fileName:"
read fileName
name1=$(makeName "type1")
name2=$(makeName "type2")
echo $name1
echo $name2
[UPDATE]
The updated question shows that you intend to read yet another value inside the makeName
function, while the function also intends to echo
some prompt for the user. So the command substitution approach will not work in that case - you need to use a global variable, like
makeName() {
echo -n "Enter Ext: "
read ext
__="$fileName.$1.$ext.log"
}
echo -n "Enter fileName:"
read fileName
makeName "type1" ; name1=${__}
makeName "type2" ; name2=${__}
echo $name1
echo $name2
$ ./sample.sh
Enter fileName:filename
Enter Ext: ext1
Enter Ext: ext2
filename.type1.ext1.log
filename.type2.ext2.log
Yet better, for cleaner code and to avoid using global variables inside your function, you could use the approach described at Returning Values from Bash Functions and pass the name of the return variable as parameter, and ideally also pass the fileName
as parameter:
makeName() {
local __type=$1
local __fileName=$2
local __resultvar=$3
local ext
local myresult
echo -n "Enter Ext: "
read ext
myresult="$__fileName.$__type.$ext.log"
eval $__resultvar="'$myresult'"
}
echo -n "Enter fileName:"
read fileName
makeName "type1" $fileName theResult ; name1=${theResult}
makeName "type2" $fileName theResult ; name2=${theResult}
echo $myresult
echo $name1
echo $name2
Side Note: See Why should eval be avoided in Bash, and what should I use instead? for a discussion why eval
should be avoided. When using bash version 3.1 or higher, you can use printf
instead of eval
:
...
printf -v "$__resultvar" '%s' "$myresult"
...
And, finally, with bash 4.3 or higher, we can assign the nameref attribute to a variable using declare -n
, so that the variable is effectively a reference to another variable:
...
declare -n myresult=$3
myresult="$__fileName.$__type.$ext.log"
...
bash: how to return string with newline from function?
Use printf
to print formatted strings.
create_string() {
printf '[%s]\nworld\n' "$1"
}
Can a string be returned from a Bash function without using echo or global variables?
No. Bash doesn't return anything other than a numeric exit status from a function. Your choices are:
- Set a non-local variable inside the function.
- Use
echo
,printf
, or similar to provide output. That output can then be assigned outside the function using command substitution.
Return value in a Bash function
Although Bash has a return
statement, the only thing you can specify with it is the function's own exit
status (a value between 0
and 255
, 0 meaning "success"). So return
is not what you want.
You might want to convert your return
statement to an echo
statement - that way your function output could be captured using $()
braces, which seems to be exactly what you want.
Here is an example:
function fun1(){
echo 34
}
function fun2(){
local res=$(fun1)
echo $res
}
Another way to get the return value (if you just want to return an integer 0-255) is $?
.
function fun1(){
return 34
}
function fun2(){
fun1
local res=$?
echo $res
}
Also, note that you can use the return value to use Boolean logic - like fun1 || fun2
will only run fun2
if fun1
returns a non-0
value. The default return value is the exit value of the last statement executed within the function.
how to return a multi-line string from a bash function call ... properly?
Your problem here is that echo
always adds a newline to the end of your string - if it already contains one, it will have two. Since you're always "returning" using echo "$result"
, every time it will add a new one.
You should try using printf "%s" "$result"
:
ini_buffer="1.2.3.4
"
echo "initial ini_buffer len: ${#ini_buffer}"
IFS= read -rd '' result < <(printf "%s" "$ini_buffer")
echo "result len: ${#result}"
Result:
initial ini_buffer len: 8
result len: 8
shell script function return a string
The first is calling the function and storing all of the output (four echo
statements) into $constr
.
Then, after return, you echo the preamble printing result
, $constr
(consisting of four lines) and the exit message.
That's how $()
works, it captures the entire standard output from the enclosed command.
It sounds like you want to see some of the echo
statements on the console rather than capturing them with the $()
. I think you should just be able to send them to standard error for that:
echo "String1 $1" >&2
Safest way to return string from bash function (4.3) when function contains other echos
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.
How to get the content of a function in a string using bash?
Make a dummy function foo(), which just prints "bar":
foo() { echo bar ; }
Now a bash
function to print what's in one (or more) functions. Since the contents of a function are indented with 4 spaces, sed
removes any lines without 4 leading spaces, then removes the leading spaces as well, and adds a ';' at the end of each function:
# Usage: in_func <function_name1> [ ...<function_name2> ... ]
in_func()
{ while [ "$1" ] ; do \
type $1 | sed -n '/^ /{s/^ //p}' | sed '$s/.*/&;/' ; shift ; \
done ; }
Print what's in foo():
in_func foo
Output:
echo bar;
Assign what's in foo() to the string $baz, then print $baz:
baz="`in_func foo`" ; echo $baz
Output:
echo bar;
Run what's in foo():
eval "$baz"
Output:
bar
Assign what's in foo() to $baz three times, and run it:
baz="`in_func foo foo foo`" ; eval "$baz"
Output:
bar
bar
bar
Returning value from called function in a shell script
A Bash function can't return a string directly like you want it to. You can do three things:
- Echo a string
- Return an exit status, which is a number, not a string
- Share a variable
This is also true for some other shells.
Here's how to do each of those options:
1. Echo strings
lockdir="somedir"
testlock(){
retval=""
if mkdir "$lockdir"
then # Directory did not exist, but it was created successfully
echo >&2 "successfully acquired lock: $lockdir"
retval="true"
else
echo >&2 "cannot acquire lock, giving up on $lockdir"
retval="false"
fi
echo "$retval"
}
retval=$( testlock )
if [ "$retval" == "true" ]
then
echo "directory not created"
else
echo "directory already created"
fi
2. Return exit status
lockdir="somedir"
testlock(){
if mkdir "$lockdir"
then # Directory did not exist, but was created successfully
echo >&2 "successfully acquired lock: $lockdir"
retval=0
else
echo >&2 "cannot acquire lock, giving up on $lockdir"
retval=1
fi
return "$retval"
}
testlock
retval=$?
if [ "$retval" == 0 ]
then
echo "directory not created"
else
echo "directory already created"
fi
3. Share variable
lockdir="somedir"
retval=-1
testlock(){
if mkdir "$lockdir"
then # Directory did not exist, but it was created successfully
echo >&2 "successfully acquired lock: $lockdir"
retval=0
else
echo >&2 "cannot acquire lock, giving up on $lockdir"
retval=1
fi
}
testlock
if [ "$retval" == 0 ]
then
echo "directory not created"
else
echo "directory already created"
fi
Related Topics
In Linux, Physical Memory Pages Belong to The Kernel Data Segment Are Swappable or Not
Customize Tab Completion in Shell
How Does Linux Support More Than 512Gb of Virtual Address Range in X86-64
Understanding Linux Directory Permissions Reasoning
How to Answer Yes in Bash Script
Execute Bash Script Remotely via Curl
Powershell's Equivalent to Linux's: Ls -Al
Transpose Rows into Column in Unix
What Ncurses Frameworks Are Available for Bash
Berkeley Db Mismatch Error While Configuring Ldap
Why Is "Autoreconf" Not Used Often
Runner Is Not Healthy and Will Be Disabled
How to Update Minikube Latest Version
How to Disable Serial Console(Non-Kernel) in U-Boot