LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-08-2021, 10:50 AM   #1
ychaouche
Member
 
Registered: Mar 2017
Distribution: Mint, Debian, Q4OS, Mageia, KDE Neon
Posts: 160

Rep: Reputation: 8
Global variables in bash


Dear LQ,

What is the "standard" way of programming in bash ? can my functions simply
change global variables inside their code and the rest of my script expects
global variables to be changed anytime, or do you write functions that take
parameters and return values ?

It is easy to receive or return a number or a string, but I still have to figure out how to receive/return multiple values.
 
Old 09-08-2021, 11:19 AM   #2
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,862

Rep: Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694
in bash you cannot return multiple values, or at least not recommended.
Better to use global variables.
you might want to start here: https://www.thegeekstuff.com/2010/05/bash-variables/ (or a similar page)
 
Old 09-08-2021, 01:01 PM   #3
teckk
Senior Member
 
Registered: Oct 2004
Distribution: FreeBSD Arch
Posts: 3,621
Blog Entries: 2

Rep: Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163Reputation: 1163
Code:
#!/usr/bin/bash

#global vars
a="cow"
b=3

funct1() {
    #local vars
    c="dog"
    d="cats"
    e="frog"
    
    #local var
    echo ""$e" > local var in funct1"
    
    #global var
    echo ""$a" > global var in funct1"
    
    #global var + local var
    f=2
    g=$(($b + $f))
}

funct2() {
    # f from funct1
    str="Mary had "$f" little lambs"
}

echo ""$a" > global var"

funct1
echo ""$c" > from funct1"
echo ""$g" > math from funct1"
echo "John likes "$d""

funct2
echo ""$str" > from funct2"

c="horses" 
echo ""$c" > var c changed"
Code:
bash ./test2.sh
cow > global var
frog > local var in funct1
cow > global var in funct1
dog > from funct1
5 > math from funct1
John likes cats
Mary had 2 little lambs > from funct2
horses > var c changed
 
Old 09-08-2021, 02:42 PM   #4
Keith Hedger
Senior Member
 
Registered: Jun 2010
Location: Wiltshire, UK
Distribution: Linux From Scratch, Slackware64, Partedmagic
Posts: 2,950

Rep: Reputation: 795Reputation: 795Reputation: 795Reputation: 795Reputation: 795Reputation: 795Reputation: 795
basically all variables in BASH are global except variables declared as 'local' in functions, and also parameters passed to functions ( $1 .. $n ).
 
Old 09-08-2021, 04:14 PM   #5
rnturn
Senior Member
 
Registered: Jan 2003
Location: Illinois (SW Chicago 'burbs)
Distribution: openSUSE, Raspbian, Slackware. Older: Coherent, MacOS, Red Hat, Big Iron IXs: AIX, Solaris, Tru64
Posts: 2,514

Rep: Reputation: 508Reputation: 508Reputation: 508Reputation: 508Reputation: 508Reputation: 508
Quote:
Originally Posted by ychaouche View Post
Dear LQ,

What is the "standard" way of programming in bash ? can my functions simply
change global variables inside their code and the rest of my script expects
global variables to be changed anytime, or do you write functions that take
parameters and return values ?
I use global variables but normally try to limit myself to using them as a global switch, say, "DEBUG=1" to turn extra messages on/off or enable/disable certain bits of code. Otherwise, I use functions though there are times when that's not always doable. If I find myself needing to return multiple values, I resort to global variables... or re-think my code so I can avoid that. Some years ago, I ran across a way to pass and return arrays to/from a shell function but it seemed so clunky and the syntax started to look like line noise on a dial-up connection. I'm not sure why it seemed like such a great idea at the time but, nowadays, feel like it's a technique best forgotten in the name of maintainability. I doubt I'd use it often enough for it to become second nature. Anyway... the folks over at Stack Overflow cover this occasionally. Worth a look if you're interested.

Quote:
It is easy to receive or return a number or a string, but I still have to figure out how to receive/return multiple values.
See above. I dislike turning shell scripts into a big "everything's global" BASIC programs. However, returning values from a function does often make debugging a bit tricky. I'll forget to send debugging messages to stderr at least once during the development and wonder why the function is returning something that's all wrong.

Cheers...
 
1 members found this post helpful.
Old 09-08-2021, 04:18 PM   #6
rnturn
Senior Member
 
Registered: Jan 2003
Location: Illinois (SW Chicago 'burbs)
Distribution: openSUSE, Raspbian, Slackware. Older: Coherent, MacOS, Red Hat, Big Iron IXs: AIX, Solaris, Tru64
Posts: 2,514

Rep: Reputation: 508Reputation: 508Reputation: 508Reputation: 508Reputation: 508Reputation: 508
Quote:
Originally Posted by Keith Hedger View Post
basically all variables in BASH are global except variables declared as 'local' in functions, and also parameters passed to functions ( $1 .. $n ).
I have, in the past, made uniquely-named shell variables inside functions to be used while they execute. Then include "unset ..." to destroy them before returning so they've no longer around for any other code to access.
 
1 members found this post helpful.
Old 09-09-2021, 12:56 AM   #7
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 17,788
Blog Entries: 11

Rep: Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384
^ I believe variables in functions are by default local unless they have been defined in the main script, and are unset once the function returns.wrong!

I once read a genius bit of advice, is to set a global RETVAL variable to avoid running functions in subshells, so instead of
Code:
do_func() { echo bla; }
string="$(do_func)"
You would do
Code:
RETVAL=""
do_func() { RETVAL=bla; }
do_func
string="$RETVAL"

Last edited by ondoho; 09-09-2021 at 11:30 PM.
 
Old 09-09-2021, 03:16 AM   #8
ychaouche
Member
 
Registered: Mar 2017
Distribution: Mint, Debian, Q4OS, Mageia, KDE Neon
Posts: 160

Original Poster
Rep: Reputation: 8
@ondoho yes, some bash builtins like read and select put their output in $REPLY.
 
Old 09-09-2021, 03:36 AM   #9
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,862

Rep: Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694
Quote:
Originally Posted by ondoho View Post
^ I believe variables in functions are by default local unless they have been defined in the main script, and are unset once the function returns.

I once read a genius bit of advice, is to set a global RETVAL variable to avoid running functions in subshells, so instead of
Code:
do_func() { echo bla; }
string="$(do_func)"
You would do
Code:
RETVAL=""
do_func() { RETVAL=bla; }
do_func
string="$RETVAL"
yes, that would be a good (or better?) approach, just the problem is if the func failed somehow and RETVAL still has a value. But anyway shell is not meant to do difficult/complex data manipulation.
 
1 members found this post helpful.
Old 09-09-2021, 03:40 AM   #10
ychaouche
Member
 
Registered: Mar 2017
Distribution: Mint, Debian, Q4OS, Mageia, KDE Neon
Posts: 160

Original Poster
Rep: Reputation: 8
@pan64 good point, which makes the function responsible to unset it or to set
it to some conventional NULL value that the caller must check before proceeding.
 
Old 09-09-2021, 03:53 AM   #11
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,862

Rep: Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694
Quote:
Originally Posted by ychaouche View Post
@pan64 good point, which makes the function responsible to unset it or to set
it to some conventional NULL value that the caller must check before proceeding.
the usual way is to use exit/return codes to know if a call was executed successfully. (exit code for apps, return code for funcs).
And yes, you can unset that variable too.
 
Old 09-09-2021, 03:54 AM   #12
ychaouche
Member
 
Registered: Mar 2017
Distribution: Mint, Debian, Q4OS, Mageia, KDE Neon
Posts: 160

Original Poster
Rep: Reputation: 8
So that would be checking $? everytime you call a function ? (if you
want to get defensive).
 
Old 09-09-2021, 03:57 AM   #13
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 16,862

Rep: Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694Reputation: 5694
yes, that is the way - if you want to be on the safe side. But also you need to implement error handling in your functions, otherwise it is just pointless.

Last edited by pan64; 09-09-2021 at 03:58 AM.
 
Old 09-09-2021, 06:32 AM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,832

Rep: Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089Reputation: 3089
I would like to clarify that ALL variables not declared as local (in a function) are global to script and ONLY variables declared with local will stay that way inside the function.
Quick example:
Code:
#!/usr/bin/env bash

f()
{
	local v1 v2 # these are the only local variables

	v1=hello
	v2=world
	v3=jiminy

	echo Inside function
	echo "$v1 -- $v2 -- $v3"
}

echo outside function with no changes
f

echo "$v1 -- $v2 -- $v3"

v1=blue

echo outside function after creating new global var v1 and assigning value
echo "$v1 -- $v2 -- $v3"

f
You will see from the output that v1/v2 are only available inside the function and after creating a new v1 outside the function it does not affect the local v1 inside the function


The above being the case, my default is to create sparing global variables and all others are local to their respective functions, even to the extent of having a main() function which is ultimately
one of the only things actually called by the script:
Code:
shebang

# the small number of global variables
declare gvar1 gvar2

func1()
{
  local lvar1 lvar2 pvar1 pvar2 # l for local and p for variables passed to function
...
}

...

main()
{
}

main "$@"

exit 0
These would be the stubs of my general format
 
Old 09-09-2021, 11:34 PM   #15
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 17,788
Blog Entries: 11

Rep: Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384Reputation: 5384
Quote:
Originally Posted by pan64 View Post
yes, that would be a good (or better?) approach, just the problem is if the func failed somehow and RETVAL still has a value.
Well that's just general quality control, you should always take care of these things, no matter the language/style you're coding in.

I just wanted to throw it in there; avoiding subshells is a bit of a pet peeve of mine. CPUs are so powerful nowadays people forget how to code as efficiently as possible.
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] BASH: Global Variables carolflb Linux - Newbie 4 01-23-2010 07:55 AM
LXer: OpenClinica Global Conference to Bring Together Global Community for Open Sourc LXer Syndicated Linux News 0 01-08-2010 10:50 AM
How to check the cpu utilization on all non global zones from Global Zone rajaniyer123 Solaris / OpenSolaris 3 10-09-2008 01:43 AM
Bash: How to setup "global" environment variables? ArthurHuang Programming 2 02-07-2008 12:24 PM
How to share a ZFS file system between a global zone and a non global zone? crisostomo_enrico Solaris / OpenSolaris 7 11-28-2007 08:20 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:24 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration