简体   繁体   中英

Can IFS be changed locally in a Bash function?

I have a function that needs to change IFS for its logic:

my_func() {
  oldIFS=$IFS; IFS=.; var="$1"; arr=($var); IFS=$oldIFS
  # more logic here
}

Can I declare IFS as local IFS inside the function so that I don't need to worry about backing its current value and restore later?

It appears to work as you desire.

#!/bin/bash
changeIFSlocal() {
    local IFS=.
    echo "During local: |$IFS|"
}
changeIFSglobal() {
    IFS=.
    echo "During global: |$IFS|"
}
echo "Before: |$IFS|"
changeIFSlocal
echo "After local: |$IFS|"
changeIFSglobal
echo "After global: |$IFS|"

This prints:

Before: |
|
During local: |.|
After local: |
|
During global: |.|
After global: |.|

Yes it can be defined!

As long as you define it local , setting of the value in the function does not affect the global IFS value. See the difference between the snippets below

addNumbers () {
    local IFS='+'
    printf "%s\n" "$(( $* ))"
}

when called in command-line as,

addNumbers 1 2 3 4 5 100
115

and doing

nos=(1 2 3 4 5 100)
echo "${nos[*]}"

from the command line. The hexdump on the above echo output wouldn't show the IFS value defined in the function

echo "${nos[*]}" | hexdump -c
0000000   1       2       3       4       5       1   0   0  \n
000000e

See in one of my answers, how I've used the localized IFS to do arithmetic - How can I add numbers in a bash script

You can designate IFS as a local variable; the local version is still used as the field separator string.

Sometimes it is useful to run a function in a completely isolated environment, where no changes are permanent. (For example, if the function needs to change shell options.) This can be achieved by making the function run in a subshell; just change the {} in the function definition to () :

f() ( 
  shopt -s nullglob
  IFS=.
  # Commands to run in local environment
)

I got confused because I changed the value of IFS to : inside the function (without using local ) and then tried to display the value of IFS with this command, after calling the function:

echo $IFS

which displayed an empty line that made me feel the function wasn't changing IFS. After posting the question, I realized that word splitting was at play and I should have used

echo "$IFS"

or

printf '%s\n' "$IFS"

or, even better

set | grep -w IFS=

to accurately display the IFS value.

Coming back to the main topic of local variables, yes, any variable can be declared as local inside a function to limit the scope, except for variables that have been declared readonly (with readonly or declare -r builtin commands). This includes Bash internal variables like BASH_VERSINFO etc.

From help local :

local: local [option] name[=value] ...

 Define local variables. Create a local variable called NAME, and give it VALUE. OPTION can be any option accepted by `declare'. Local variables can only be used within a function; they are visible only to the function where they are defined and its children. Exit Status: Returns success unless an invalid option is supplied, a variable assignment error occurs, or the shell is not executing a function. 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM