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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.