5

I am new to shell scripts, I am trying to create a simple function which will return the concatenated two strings that are passed as parameters. I tried with below code

   function getConcatenatedString() {
       echo "String1 $1"
       echo "String2 $2"
       str=$1/$2
       echo "Concatenated String ${str}"
       echo "${str}"
   }

//I am calling the above function

  constr=$(getConcatenatedString "hello" "world")
  echo "printing result"
  echo "${constr}"
  echo "exit"

I see the below output when running the script with above code,

   printing result
   String1 hello
   String2 world
   Concatenated String hello/world
   hello/world
   exit

If you look at the code I am first calling the function and then I am echoing "printing result" statement, but the result is first comes the "printing result" and echos the statement inside the function. Is the below statement calling the function

   constr=$(getConcatenatedString "hello" "world")

or

   echo ${constr}

is calling the function ?

Because if I comment out #echo ${constr} then nothing is getting echoed !!! Please clarify me.

Lolly
  • 34,250
  • 42
  • 115
  • 150

3 Answers3

10

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
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

paxdiablo's solution is correct. You cannot return a string from a function, but you can capture the output of the function or return an integer value that can be retrieved by the caller from $?. However, since all shell variables are global, you can simply do:

getConcatenatedString() { str="$1/$2"; }      
getConcatenatedString hello world
echo "Concatenated String ${str}"

Note that the function keyword is redundant with (), but function is less portable.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
1

A more flexible, but slightly harder to understand approach is to pass a variable name, and use eval so that the variable becomes set in the caller's context (either a global or a function local). In bash:

function mylist()
{
    local _varname=$1 _p _t
    shift

    for _p in "$@"; do
        _t=$_t[$_p]
    done

    eval "$_varname=\$_t"
}

mylist tmpvar a b c
echo "result: $tmpvar"

On my Linux desktop (bash-3.2) it's approx 3-5x faster (10,000 iterations) than using ``, since the latter has process creation overheads.

If you have bash-4.2, its declare -g allows a function to set a global variable, so you can replace the unpretty eval with:

declare -g $_varname="$_t"

The eval method is similar to TCL's upvar 1, and declare -g is similar to upvar #0.

Some shell builtins support something similar, like bash's printf with "-v", again saving process creation by assigning directly to a variable instead of capturing output (~20-25x faster for me).

mr.spuratic
  • 9,767
  • 3
  • 34
  • 24