The UNIX and Linux Forums

The UNIX and Linux Forums (http://www.unix.com/index.php)
-   Linux (http://www.unix.com/linux/)
-   -   Peculiar behavior due to IFS (http://www.unix.com/linux/217229-peculiar-behavior-due-ifs.html)

ravisingh 03-27-2013 03:41 AM

Code:

$ cat emp.lst
Rob Mills
Jack Thompson
Steffi Blues

a=`cat emp.lst`
echo $a

The output of this echo shows the 3 names in a single line which is perfectly fine.

But my doubt is with the below:
Code:

echo "$a"
The output of this shows the 3 names in 3 lines.
Please see, now also I expected the same output because the variable a is already defined. When above I defined the variable "a", the command cat emp.lst was not quoted and hence variable "a" should not have accepted a newline character.
But this output says that the var. "a" has accepted the newline character.
How come this happen?

Corona688 03-27-2013 12:45 PM

What was IFS set to at the time?

alister 03-27-2013 01:21 PM

Quote:

Originally Posted by ravisingh (Post 302786167)
Code:

a=`cat emp.lst`
...

When above I defined the variable "a", the command cat emp.lst was not quoted and hence variable "a" should not have accepted a newline character.

Variable assignments bypass field splitting and pathname expansion (aka file globbing). IFS is irrelevant.

Since double quotes prevent field splitting and pathname expansion from occurring (the only sh parsing steps which can increase the number of elements in a command line), a="`cat emp.lst`" is equivalent to your unquoted version.

The newlines that you mention are in $a. The difference you observe is a result of quoting or not quoting echo's argument. The newlines are consumed by field splitting when the shell parses echo $a . The difference between the two echo commands is that in the quoted version, the shell is invoking echo with one argument, which contains three lines of names. In the unquoted version, the shell itself looks at the contents of $a, splits it on whitespace, consuming the newlines and (this is important) the spaces as well. echo is then invoked with 6 arguments, one for each word of the names. It is echo's job to then take its 6 arguments, join them with a single space between each, and print the result. In the quoted version, since echo is only passed a single argument, it does not add any space characters.

Note that command substitution always strips trailing newlines (not embedded). This has nothing to do with quoting, field splitting, IFS, nor variable assignment. It's how command substitution is designed. You may not have noticed that because echo, besides joining its arguments with a space character, appends a newline. If, however, your file has multiple newlines at the end, you will notice that when you echo the contents of a double-quoted $a, only a single newline is present (all trailing newlines were stripped by the command substitution but only one is added by echo).

Regards,
Alister

Corona688 03-27-2013 01:23 PM

Quote:

Originally Posted by alister (Post 302786465)
Variable assignments bypass field splitting and pathname expansion (aka file globbing). IFS is irrelevant.

Interesting disctinction. I've also noticed that IFS applies here:
Code:

set -- `cat file`
But not here:

Code:

set -- $(cat file)

alister 03-27-2013 02:14 PM

Quote:

Originally Posted by Corona688 (Post 302786469)
Interesting disctinction.

It makes sense when you consider the effect that field splitting or pathname expansion could have. a=$1 could yield a=word1 word2 which would then execute an unintended command, word2, with a modification to its environment.

This bypassing of actions which can increase the number of tokens also occurs in the case statement: In case word in ... , word is not subject to field splitting and pathname expansion.


Quote:

Originally Posted by Corona688 (Post 302786469)
Interesting disctinction. I've also noticed that IFS applies here:
Code:

set -- `cat file`
But not here:

Code:

set -- $(cat file)

I have not been able to reproduce such behavior nor have I been able to find any documentation implying that such behavior is intentional. Perhaps there's a bug in your shell? Can you specify the shell and demonstrate how you trigger such behavior?

I tried the following on bash 3.1.17 and did not observe any command substitution syntax-dependent difference in field splitting:
Code:

$ echo 1 2 3 > file

$ # With the default value of IFS, <space><tab><newline>
$ # Unquoted

$ set --; echo $#
0
$ set -- `cat file`; echo $#
3
$ set --; echo $#
0
$ set -- $(cat file); echo $#
3

$ # Quoted
$ set --; echo $#
0
$ set -- "`cat file`"; echo $#
1
$ set --; echo $#
0
$ set -- "$(cat file)"; echo $#
1

Regards,
Alister

Corona688 03-27-2013 02:41 PM

Interesting. I have bash 4, and thought I could depend on $( ) not splitting. Apparently not so.

ravisingh 03-28-2013 04:53 AM

Rudic, got it.
Is it that the below variable assignment will work ?
Code:

$ a=`echo how are you`
I think as variable assignment is shell built-in, shell takes care that a is assigned the 3 words"how are you" even if the echo command is unquoted with double-quote.
---------------------------------------------------------------------------------
Also, 1 more point I had been thinking since long.
For example:
Code:

grep "$a" emp.lst
Who interprets double quote here: shell or grep or both?
According to me it's both.


All times are GMT -4. The time now is 05:15 PM.

Linux and Unix Supported by: vBulletin
Search Engine Optimisation provided by DragonByte SEO v1.1.4 (Pro) - vBulletin Mods & Addons Copyright © 2014 DragonByte Technologies Ltd.
The UNIX and Linux Forums Content Copyright ©1993-2013. All Rights Reserved.
Forum Operations by The UNIX and Linux Forums