1

I am having a problem reconciling all of the field expansions rules in linux/unix, so I've been experimenting. Here is an example which based on my reading is not consistent with what I'd expect.

~$ IFS=$', \t\n'
~$ for i in 1 2 3; do echo num:"$i"; done
num:1
num:2
num:3
~$ myvar=1,2,3
~$ for i in $myvar; do echo num:"$i"; done
num:1
num:2
num:3
~$ for i in 1,2,3; do echo num:"$i"; done
num:1,2,3

The last output to me is completely unexpected. Where might I find the rule where field expansion only happens in a bash for loop for variables?

It seems to me that the bash for loop isn't honoring the IFS value that I setup at the beginning. Am I misunderstanding something?

2 Answers 2

2

Field Splitting only apply on result of parameter expansion, command substitution and arithmetic expansion which did not occur in double quotes, not the literal string.

Using $myvar, you have the effect as glob(split(1,2,3)), split(1,2,3) with , contains in IFS return 1, 2 and 3, glob(1 2 3) return 1, 2 and 3.

Literal string 1,2,3 was not affected by that process and just return as-is.

8
  • Thank you for you answer, I see now that it seems that these 3 rules that cause field splitting all use the $ prefix, which makes some sense in terms of consistency. However, why does for i in 1 2 3; do ... done split 1 2 3 properly? Feb 10, 2016 at 16:59
  • @JohnCarpenter: It was not split. 1 2 3 is a list contains 3 elements 1, 2 and 3. While 1,2,3 is a list contain one element 1,2,3. Space is used to delimited shell token, read more details here
    – cuonglm
    Feb 10, 2016 at 17:02
  • ah, OK. Array initialization in bash uses whitespace, and doesn't use the IFS environment variable link. This was where my confusion was coming from. Last question: is saying "field splitting returns an array of fields" an accurate way to think of field splitting? I'm just trying to make sure that I understand this completely so I have more confidence with the basics Feb 10, 2016 at 17:09
  • @JohnCarpenter: No, it break long string into one or more fields (or words).
    – cuonglm
    Feb 10, 2016 at 17:11
  • So a for loop is able to iterate through an array, or a result of a field expansion as if they were the same thing? I apologize, I'm not trying to be dense! Feb 10, 2016 at 17:13
1

Execute this command:

LESS=+/'^ *IFS *The' man bash

To read ( “emphasis mine” ):

IFS
The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is `<space><tab><newline>'.

That means that if expansion did not take place, IFS field splitting also does not take place.

Well, actually, spliting does take place in the original line but with the fix set of metacharacters | & ; ( ) < > space tab

The comma , is not a metacharacter and is not used to split.

The chapter seven of this book has more detail about command-line processing:

  1. Splits the command into tokens that are separated by the fixed set of metacharacters: SPACE, TAB, NEWLINE, ;, (, ), <, >, |, and &. Types of tokens include words, keywords, I/O redirectors, and semicolons.

  1. Takes the parts of the line that resulted from parameter, command, and arithmetic substitution and splits them into words again. This time it uses the characters in $IFS as delimiters instead of the set of metacharacters in Step 1.
1
  • @John Carpenter: That's token recognition, not related to fields splitting. It's parsing process.
    – cuonglm
    Feb 11, 2016 at 19:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .