differecnce between ${IFS} and "${IFS}"

differecnce between ${IFS} and "${IFS}"

Post by Decar » Tue, 09 Mar 2010 22:55:54


The following two commands have different effect.

$ echo A${IFS}B
A B

$ echo "A${IFS}B"
A
B

It is obvious that the first one interprets `IFS' as
space, while the second interprets it as new line.
In fect, the `IFS' represents three characters, namely
space, tab, and new line. why different choices occur
in different situations?

--
ego cogito ergo sum
 
 
 

differecnce between ${IFS} and "${IFS}"

Post by pk » Tue, 09 Mar 2010 22:59:36


It's not like you think. There's no "interpretation" whatsoever, only normal
shell operation. Run the output through "od -c":

$ echo A${IFS}B | od -c
0000000 A B \n
0000004
$ echo "A${IFS}B" | od -c
0000000 A \t \n B \n
0000006

Hint: when using double quotes, word splitting does not happen.

 
 
 

differecnce between ${IFS} and "${IFS}"

Post by mop2 » Wed, 10 Mar 2010 00:15:02


As already said, your question is not about the variable "IFS",
but about the command "echo":

$ A=$'A\tB\nC D\n\n'
$ echo "$A"
A B
C D


$ echo $A
A B C D
$ echo "$A"
A B
C D


$
 
 
 

differecnce between ${IFS} and "${IFS}"

Post by Dominic Fa » Wed, 10 Mar 2010 00:17:12


IFS is appropriately interpreted, by the shell, however, \t
and \n are control characters, so the shell removes them,
because they are not protected by quotes.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
 
 

differecnce between ${IFS} and "${IFS}"

Post by Janis Papa » Wed, 10 Mar 2010 00:19:23


No, it has nothing to do with the echo command (or builtin).
It's about word splitting, as pk already said.

Janis
 
 
 

differecnce between ${IFS} and "${IFS}"

Post by Dominic Fa » Wed, 10 Mar 2010 00:33:32


Ignore that one, it's all wrong.

This is actually a word splitting issue as other posters have
pointed out.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
 
 

differecnce between ${IFS} and "${IFS}"

Post by Decar » Wed, 10 Mar 2010 02:58:46

pk < XXXX@XXXXX.COM > writes:




The output of command od is just the result.
But, what is the meaning of `normal shell operation'?
What does cause shell expand the former to a space, the
latter to three characters?
Does word splitting matter? Any hints about it is appreciated.

--
ego cogito ergo sum
 
 
 

differecnce between ${IFS} and "${IFS}"

Post by pk » Wed, 10 Mar 2010 04:10:56

ecare wrote:


That "result" shows what's really happening, and shows that in the second
case IFS is not "interpreted as newline", but is instead left untouched with
its original value, including space and tab.


Exactly because of word splitting.

(simplified explanation, but appropriate for this case, follows)

After the value of the variabile has been replaced, *if the variable does
not appear between double quotes*, the shell performs word splitting, that
is, sequences of blanks (like space, tab and newline) are replaced with a
single space (they are actually replaced with the first character of $IFS,
which happens to be a space). Then, each "word" obtained this way is treated
as a separate argument to the command that the shell will run. In your case,

A${IFS}B

becomes (after variable substitution)

A \t\nB

word splitting turns the " \t\n" sequence into a single space. The result is
thus two arguments "A" and "B", which are passed to echo.

If you use double quotes, word splitting does not happen within them. So

"A${IFS}B"

after variable substitution becomes

A \t\nB

and, because it was in double quotes, that is preserved and passed *as a
single argument* to echo.

Anoter example of word splitting:

$ ls
file1 file2 file3
$ a=`ls`
$ echo "$a" # no word splitting, everything's preserved
file1
file2
file3
$ echo $a # word splitting kicks in
file1 file2 file3

Yet another example. $# is a special variable representing the number of
arguments received by a script.

$ ls
file1 file2 file3
$ a=`ls`
$ sh -c 'echo "Number of arguments: $#"' sh "$a"
Number of arguments: 1
$ sh -c 'echo "Number of arguments: $#"' sh $a
Number of arguments: 3

To return to your example:

$ sh -c 'echo "Number of arguments: $#"' sh A${IFS}B
Number of arguments: 2
$ sh -c 'echo "Number of arguments: $#"' sh "A${IFS}B"
Number of arguments: 1

Your shell should have a good description of the word splitting process in
the man page. If this helps, this is what bash man page says (slightly
reformatted):

Word Splitting
The shell scans the results of parameter expansion, command
substitution, and arithmetic expansion that did not occur within dou?
ble quotes for word splitting.

The shell treats each character of IFS as a delimiter, and splits the
results of the other expansions into words on these charac?
ters. If IFS is unset, or its value is exactly
<space><tab><newline>, the default, then sequences of <space>,
<tab>, and <newline> at the beginning and end of the results of
the previous expansions are ignored, and any sequence of IFS
characters not at the beginning or end serves to delimit words. If
IFS has a value other than the default, then sequences of the
whitespace characters space and tab are ignored at the beginning and
end of the word, as long as the whitespace character is in the value
of IFS (an IFS whitespace character). Any character in IFS that is
not IFS whitespace, along with any adjacent IFS whitespace charac?
ters, delimits a field. A sequence of IFS whitespace characters is
also treated as a delimiter. If the value of IFS is null, no word
splitting occurs.

 
 
 

differecnce between ${IFS} and "${IFS}"

Post by pk » Wed, 10 Mar 2010 05:20:29


This is actually incorrect. I was getting confused with something else.
They're not actually replaced with anything; what matters is that the
sequence of blanks is treated as a word separator.
Sorry for the confusion.
 
 
 

differecnce between ${IFS} and "${IFS}"

Post by Seeb » Wed, 10 Mar 2010 05:42:18


Yes, they do.




Actually, it is not obvious at all that the first one interprets
IFS as space, or the second interprets it as new line.

In the first one, there's no quotes. When you expand any variable
unquoted, it is then split into fields... By removing any characters
from $IFS and replacing them with a separation-of-fields. Thus, you
end up producing two arguments to echo, "A" and "B". These arguments
are then echoed, with a space between them.

In the second, there's quotes. When you expand a variable inside quotes,
it is not split into fields. So you pass a single argument to echo,
which argument happens to contain a space, tab, and newline. So it
echoes A, space, tab, newline, B. But you can't see the space and tab.

You can see this as follows:

#!/bin/sh
for i
do
echo "<$i>" | sed -e 's/^/:/g' -e 's/$/:/g'
done

$ ./args A${IFS}B
:<A>:
:<B>:
$ ./args "A${IFS}B"
:<A :
:B>:

In short: If you think something is obvious, and you don't understand it,
it probably isn't really obvious. In this case, your interpretation of the
output was wrong in both cases, and that was the source of the confusion.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / XXXX@XXXXX.COM
http://www.yqcomputer.com/ ;-- lawsuits, religion, and funny pictures
http://www.yqcomputer.com/ (Scientology) <-- get educated!