9

Is there a possible way to initialize a global variable in bash and assign it a value in a function, then use it out side the function scope?

Function example:

globla_var=""

_DBINFO()
{
  curl  -su $AUTH https://<balla bla >/databases | jq -c 'map(select(.plan.name != "Sandbox")) | .[] | {id, name}'| \
  while  read db
  do
    idb=$(echo "$db" | jq -r '.id')
    name=$(echo "$db" | jq -r '.name')
    if [[ $name = '<bla>' ]]; then
        $global_var_her = $(<bla value>)
     fi
  done
}

then use it outside the function:

 echo $global_var

the result

   $0: line 16: =<bla bla>: command not found

I tried using declare:

declare -r global_var

same results

3
  • 3
    In fact, variables in a function are global by default; local variables must be explicitly declared using either the local or declare builtins. Commented Oct 27, 2015 at 19:45
  • there is a typo at the beginning globla_var which should be global_var as I believe. Commented Jul 24, 2021 at 8:48
  • @ÖmerAn Furthermore, _DBINFO() uses $global_var_her, not $global_var nor $globla_var. Commented Dec 31, 2024 at 12:41

5 Answers 5

8

Yes you can, but you have to be careful about subshells that limit scope in unexpected ways. Piping to a while read loop like you are doing is a common pitfall.

Instead of piping to a while read loop, use redirection and process substitution:

_DBINFO()
{     
  while read db
  do
    idb=$(echo "$db" | jq -r '.id')
    name=$(echo "$db" | jq -r '.name')
    if [[ $name = '<bla>' ]]; then
        global_var=value
     fi
  done  <  <(curl  -su "$AUTH" "https://$host/databases" |
               jq -c 'map(select(.plan.name != "Sandbox")) | .[] | {id, name}')
}

AUTH="user:password"
host="example.com"
_DBINFO
echo "The global variable is $global_var"

You also need to make sure your assignment is syntactically valid. $var = value is not a valid bash assignment, while var=value is. shellcheck can point out many things like that.

Sign up to request clarification or add additional context in comments.

Comments

4

Maybe you're confusing bash with php. Just remove the $, the _her part, and the space:

global_var=$(<bla value>) # or maybe: global_var=`<bla value>`

instead of:

$global_var_her = $(<bla value>)

With that, the error goes away.


On the other hand, check that other guy's answer regard to the pipelines.

And yes, it is possible to define a global variable and it is done the way you're doing it.


Maybe is useful pointing something about this:

$(<bla value>)

If <bla value> is a command, the sentence is ok, because that't the way to capture the output of a command with Command Substitution.

If, instead, is a literal value, just remove the $() leaving just '<bla value>' (global_var='<bla value>'). This is the same to do $(echo '<bla value>') but that would be an unnecessary waste of resources.

Comments

3

This is already answered, but I'd give it a shorter solution

test() { declare x="Important output"; }

test && echo $x

Will leave us with no output, while the answer has a workaround, here's what I suggest to use

test() { export x="Important output"; }

test && echo $x

Will give us an output

1 Comment

This does not address the problem at hand though - while you can read it, you still can't write to it in a way that propagates to the parent shell.
2

All variables have global scope, unless declared local inside some function.

So, all the vars in your program are valid outside the function.
But there are several problems:

  1. You are sending the output of curl ... with a pipe |. That creates a sub-shell. Variables changed inside a sub-shell are not translated to global.
  2. The name of the var was globla_var="". Is that a typo? Should it be global_var?.
  3. There is an space before and after the = in: $global_var_her = "bla". That is incorrect syntax in bash, and in shell in general.
  4. There is a $ on the left side of an equality. That does not assign to the variable global_var_her.
  5. There is an additional _her which seems UN-needed.

All corrected, this should work:

global_var=""

_DBINFO(){

    content=$(
        curl  -su $AUTH https://<balla bla >/databases |
        jq -c 'map(select(.plan.name != "Sandbox")) | .[] | {id, name}'
    )

    while  read -r db
    do
        idb=$(echo "$db" | jq -r '.id')
        name=$(echo "$db" | jq -r '.name')
        if [[ $name = '<bla>' ]]; then
            global_var=$(echo "<bla value>")
        fi
    done <<<"$content"

}

Comments

0

Try declare -g. From declare help page:

-g  create global variables when used in a shell function; otherwise
    command.  The `-g' option suppresses this behavior.
f() {
    declare -g newvar="It works!";
}
f
echo $newvar;  # It works!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.