IFS setup for one operator

On my GNU bash, version 4.3.42(1)-release I do some tests to answer the question . The idea is to split a : -separated string and each of its elements into an array.

To do this, I try to set IFS in : in the scope of the command so that the split is automatic and the IFS remains untouched:

 $ myvar="a:b:c" $ IFS=: d=($myvar) $ printf "%s\n" ${d[@]} a b c 

And, obviously, IFS remains unchanged:

  $ echo $ IFS
                       # empty

The BASH link says that:

If IFS is not specified, parameters are separated by spaces. If IFS is null, the parameters are joined without intermediate delimiters.

However, I noticed that IFS is incorrect, so echo $myvar returns abc instead of a:b:c .

Cancels the value:

 $ unset IFS $ echo $myvar a:b:c 

But I wonder: what causes this? Is IFS=: command change to IFS only in the scope of the command being executed?

I see in the IFS setup for one statement that this really works:

 $ IFS=: eval 'd=($myvar)' $ echo $myvar a:b:c 

But I don’t understand why he does it, and IFS=: d=($myvar) does not work.

+5
source share
3 answers

I was going to comment on this when I saw that you were using it, but it didn’t occur to me until there was a problem just now. Line

 IFS=: d=($myvar) 

temporarily not established by IFS ; it just sets two variables in the current shell. (Simple commands may have a prefix with local environment settings, but the assignment statement itself is not a simple command.)

When you write

 echo $IFS 

IFS expands to : but since : is the first IFS character, it is deleted when the word is split. Using

 echo "$IFS" 

will show that the IFS is still set to :

+7
source

IFS behaves fine with read on the same line:

 myvar="a:b:c" IFS=: read -ra d <<< "$myvar" printf "%s\n" "${d[@]}" a b c 

Check IFS value:

 declare -p IFS -bash: declare: IFS: not found 

therefore, it is clear that IFS not been changed in the current shell.

Now check the original input:

 echo $myvar a:b:c 

or

 echo "$myvar" a:b:c 
+3
source

In bash, you can set the value of a variable that is valid for a single statement only if that statement alone is not a variable assignment. For instance:

 $ foo=one bar=two $ echo $foo one 

To do the second part of the assignment, you need ... another expression. As you noticed, eval works. Also, read should work:

 $ foo="one:two:three" $ IFS=: read -r -a bar <<< "$foo" $ declare -p bar declare -a bar='([0]="one" [1]="two" [2]="three")' 
+1
source

Source: https://habr.com/ru/post/1234796/


All Articles