BUG: IFS affects var, during var assignment in 'local'

During var assignment, var doesn't have to be put inside "", to be protected from IFS.
However, inside of a function, on line 'local mf_var=$...', IFS does kicks in!

Code:
#!/bin/sh


cust_data=32
IFS=2


my_fun ()
{
    local mf_var=$cust_data

    echo "Var defined in function's local: '$mf_var'"


    other_var=$cust_data

    echo "Var defined regulary: '$other_var'"
}


my_fun
Pls, don't reply before testing code. ;)
 
Seeker said:
During var assignment, var doesn't have to be put inside "", to be protected from IFS.
However, inside of a function, on line 'local mf_var=$...', IFS does kicks in!
That's because the IFS variable has a global scope. To prevent this from happening put quotes around the assignment:
Code:
local mf_var="$cust_date"
 
No, it is not because IFS variable has a global scope, because
Code:
other_var=$cust_data
inside of a function doesn't have to be protected from IFS via ""

Uncomment/Comment out IFS, as pleased:
Code:
#!/bin/sh


cust_data=32
#IFS=2


my_fun ()
{
    local IFS=2
    local mf_var=$cust_data

    echo "Var defined in function's local: '$mf_var'"


    other_var=$cust_data

    echo "Var defined regulary: '$other_var'"
}


my_fun


ot_var=$cust_data

echo "Var defined outside regulary: '$ot_var'"
 
Seeker said:
because
Code:
other_var=$cust_data
inside of a function doesn't have to be protected from IFS via ""
This is incorrect. A variable must always be quoted or else IFS will interfere. It doesn't matter if it's inside a function or not.
 
No, it is incorrect, that you state this is incorrect. You are adding to the confusion and not to the solution.
Executed code is the witness.
A variable must always be quoted or else IFS will interfere.
NOPE! In a case, where it is being assigned into another variable. (Regardless of is it in function or outside)
'local var=$...', breaks this rule

PROOF: (Code output)
Code:
# NONE of them is double quoted
Var defined in function's local: '3'
Var defined regulary: '32'
Var defined outside regulary: '32'
Let some dev comment on this.
Code:
 
Hmm, yeah, the meds were wearing off which means I post before I think.

I tried to test this on Solaris 8 and 10 but its shell doesn't seem to support the local keyword at all :(

Trying it on Linux will give skewed results as their /bin/sh is actually bash with a few options turned off.

And I couldn't find a lot of information about the special handling of IFS, except that it's used to separate fields.

I did manage to test it on FreeBSD 4.10 and that produces an error on the local line with the first script:
Code:
%./test.sh
local: : bad variable name
Var defined in function's local: '3'
Var defined regulary: '32'
 
Ah... that actually made me look a little closer..

Code:
local myvar=$something

Is the bug. According to the sh(1) man page the local keyword only accepts a variable name as its argument. This produces the correct result:
Code:
local myvar
myvar=$someother
 
Although various shells such as bash, ksh93 and zsh handle this in a more expected manner, FreeBSD sh follows a literal reading of POSIX here. Variable assignments (before a command word or if there is no command word at all) are expanded differently from other words in a simple command; parameters to export, readonly and local that look like assignments are expanded like other words (i.e. word splitting and pathname generation applies, tilde expansion is only done at the start of the word). Consequently, the behaviour you see is expected and not a bug.

I think expanding such words as variable assignments may be useful and avoid some surprises, but as long as there is no decision about special cases such as the below I don't want to add it to sh (dash's maintainer thinks the same):
Code:
w='a b c'
command export v=$w
cmd=export
$cmd v=$w

Furthermore, note that in the command below, the inner command's exit status is discarded, which would not be so if the assignment were separated:
Code:
export v="$(cat /foo/bar)"

In addition to the POSIX concerns, local adds some more complexity. Because it is very unlikely to be added to POSIX (basically because ksh93 wants only static scoping while bash, mksh and zsh want only dynamic scoping), it cannot be a special builtin and can therefore be overridden with a function. What should this do?
Code:
local() { printf '[%s]\n' "$@"; }
w='a b c'
local v=$w
 
Thx for your explanation.
Then, I'll change/purify my coding tech.

To export, readonly and local, provide only raw variable's names:
Code:
local var_one var_two var_three
...
w='a b c'
v=$w; export v

readonly w
 
Back
Top