Clearing the echo history - bash

I have a bash script that calls a function which returns a value. I have included the scripts below:
Script
source ./utilities/function1.sh
result=$(Function1)
echo "Result: $result"
Function1
function Function1 {
echo "Inside Function: Function1"
cat <<EOF
this is the result
EOF
}
I want to be able to echo to the console within the function and return only the value I want, not including the messages that were echoed to the console, but when I run the script the following is returned:
Result: Inside Function: Func1
this is the result
Is this the best way to return a value from a bash function or is there a way I can echo to the console and return a value without the content of the echo commands from the function?
Thanks in advance

There are a few ways to do what you want. two simple ones are:
Use STDERR to echo to the console and capture STDOUT in your script. By default, STDOUT is on File Descriptor 1 and STDERR is on File Descriptor 2:
function myFunction() {
echo "This goes to STDOUT" >&1 # '>&1' is the default, so can be left out.
echo "This goes to STDERR" >&2
}
result=$(myFunction)
echo ${result}
Use a variable to return a string to the caller:
function myFunction() {
echo "This goes to STDOUT"
result="This goes into the variable"
}
declare result="" # Has global scope. Can be modified from anywhere.
myFunction
echo ${result}
Global scope variables are not good programming practice, but are a necessary evil in bash scripting.

Related

Using global variables in functions with parameters in bash

I'm trying to catch a return value from a function in bash, that modify a global variable.
Works perfectly with funtions with no parameters:
#!/bin/bash
tes=2
testfunction(){
tes=3
tes_str="string result"
return 0
}
if output=testfunction; then
echo "OK"
else
echo "KO"
fi
echo $tes
echo $tes_str
But no with parameters:
#!/bin/bash
tes=2
testfunction(){
tes=3
tes_str="string result"
return 0
}
if output=$(testfunction "AA" "BB"); then
echo "OK"
else
echo "KO"
fi
echo $tes
echo $tes_str
Because for bash, parameters ("AA" or "BB") are a command, and I must put it in backets (but if use backets, can't modify global variables).
How can I do it? I'm stucked.
Regards
Why use output? Just remove it and run the function.
if testfunction; then
Notes:
output=testfunction is assigning the text testfunction to the variable output.
output=$(testfunction) will not work, because $(...) runs everything inside a subshell.

Running function with read command in bash

I need small help with shell function.
I created small function with read command inside, I need to call this function and the return value to outside variable
Check()
{
echo "type something : "
read anyword
echo $anyword
}
out=`Check`
echo $out
the problem is that echo line is not presenting anything until i press enter.
I want that this function will act like python.
Thanks,
The problem is the backticks. If you CTRL+C before the prompt ends, and try to echo $out, you notice that your prompt is saved into the $out variable. Move the prompt outside the function call. Maybe this will help:
Check()
{
read anyword
echo $anyword
}
echo "type something : "
out=`Check`
echo $out
If you're using bash specifically, consider read -p also.
Alternatively, if you want to keep the prompt inside the function:
Check()
{
echo "Type something: " >&2
read anyword
echo $anyword
}
That way, it will write to stderr instead of stdout, so it won't get eaten up.

Echo output to terminal within function in BASH

I am writing a script in BASH. I have a function within the script that I want to provide progress feedback to the user. Only problem is that the echo command does not print to the terminal. Instead all echos are concatenated together and returned at the end.
Considering the following simplified code how do I get the first echo to print in the users terminal and have the second echo as the return value?
function test_function {
echo "Echo value to terminal"
echo "return value"
}
return_val=$(test_function)
Yet a solution other than sending to STDERR (it may be preferred if your STDERR has other uses, or possibly be redirected by the caller)
This solution direct prints to the terminal tty:
function test_function {
echo "Echo value to terminal" > /dev/tty
echo "return value"
}
-- update --
If your system support the tty command, you could obtain your tty device from the tty command, and thus you may:
echo "this prints to the terminal" > `tty`
send terminal output to stderr:
function test_function {
echo "Echo value to terminal" >&2
echo "return value"
}
Dont use command substitution to obtain the return value from the function
The return value is always available at the $? variable. You can use the variable rather than using command substitution
Test
$ function test_function {
> return_val=10;
> echo "Echo value to terminal $return_val";
> return $return_val;
> }
$ test_function
Echo value to terminal 10
$ return_value=$?
$ echo $return_value
10
If you don't know in which terminal/device you are:
function print_to_terminal(){
echo "Value" >$(tty)
}

How to exit a bash function that expects a return

I'm not completely clear on the how/why bash's exit keyword is inconsistant when calling a function that expects a return vs. not expecting a return.
For instance, in the following repro:
#!/bin/bash
exitfunc()
{
echo "Flag 1"
exit
}
exitfunc
echo "We should never see this."
We see the output:
$ ./z.bash
Flag 1
However in this slight modification:
#!/bin/bash
exitfunc()
{
echo "Flag 1"
exit
}
foo=exitfunc
echo "We should never see this."
The output shows that the function clearly does not exit the shell.
$ ./z.bash
We should never see this.
It seems that the Flag 1 in the second version is the value stored in foo, possibly to store an error code. My question is, why does exit have this behavior in a function called in this way? Does it open a new shell when a function expects a return? How is one supposed to properly exit one of these functions? Do I just need to check the output value of foo and include exit catchers all the way up the call stack?
Thanks.
When you do foo=exitfunc, you are assigning a string exitfunc to the variable foo, not executing a function. In order to execute the function, you should do foo=$(exitfunc) instead. Then the variable foo will contain the output of the function, "Flag 1". This is known as a command substitution.
The call to exit terminates the subshell within which the function has been executed, not the shell which it was called from. In order to exit the host shell, you can do something like this:
#!/bin/bash
exitfunc()
{
echo "Flag 1"
exit 1
}
foo=$(exitfunc) || exit
echo "We never see this."
The exit status is non-zero, so the host shell exits before the last line.
The return code of the function is stored in the variable $?, so if you want to use $foo before exiting, you can do something like this:
#!/bin/bash
exitfunc()
{
echo "Flag 1"
exit 1
}
foo=$(exitfunc)
e=$?
echo "$foo"
if [ $e -ne 0 ]; then exit; fi
echo "We never see this."
Output:
Flag 1
When you call:
foo=$(exitfunc)
OR old fashioned:
foo=`exitfunc`
function exitfunc is executed in a forked sub-shell due to command substitution, hence exit only terminates the sub-shell or child shell not the current shell. Hence echo statement after foo assignment is printed since this echo is executed in current shell.

global variable value not set inside a function in shell script

I have two shell script like as follows:
a.sh
tes=2
testfunction(){
tes=3
echo 5
}
testfunction
echo $tes
b.sh
tes=2
testfunction(){
tes=3
echo 5
}
val=$(testfunction)
echo $tes
echo $val
In first script tes value is '3' as expected but in second it's 2?
Why is it behaving like this?
Is $(funcall) creating a new sub shell and executing the function? If yes, how can address this?
$() and `` create new shell and return output as a result.
Use 2 variables:
tes=2
testfunction(){
tes=3
tes_str="string result"
}
testfunction
echo $tes
echo $tes_str
output
3
string result
Your current solution creates a subshell which will have its own variable that will be destroyed when it is terminated.
One way to counter this is to pass tes as a parameter, and then return* it using echo.
tes=2
testfunction(){
echo $1
}
val=$(testfunction $tes)
echo $tes
echo $val
You can also use the return command although i would advise against this as it is supposed to be used to for return codes, and as such only ranges from 0-255.Anything outside of that range will become 0
To return a string do the same thing
tes="i am a string"
testfunction(){
echo "$1 from in the function"
}
val=$(testfunction "$tes")
echo $tes
echo $val
Output
i am a string
i am a string from in the function
*Doesnt really return it, it just sends it to STDOUT in the subshell which is then assigned to val

Resources