bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The IFS variable - a confusing issue.


From: Paul Jarc
Subject: Re: The IFS variable - a confusing issue.
Date: Thu, 07 Oct 2004 16:03:16 -0400
User-agent: Gnus/5.110003 (No Gnus v0.3) Emacs/21.3 (gnu/linux)

cga <cga9999@softhome.net> wrote:
> the pipeline on line 6 generates a space-delimited list of files -
> i.e. "file1 file2 file3 ... file99"

Newline-delimited, actually.

> but unfortunately, since the IFS variable now contains only ":" this
> leads the "for" command on line 7 to believe that it is dealing with
> a one-item list

Right.

> I replaced line 2 by the following:
>
>       2 IFS=${IFS}:
>
> .. and apparently got the above code to work.

You could also save the original IFS, set it to ":", split $PATH, and
then restore the original value:
old_ifs=$IFS
IFS=:
set -f # disable globbing, in case $PATH contains any odd characters
set -- $PATH
set +f
IFS=$old_ifs
for d in "$@"; do ...

This way, you can be sure that you will split $PATH only on colons,
not whitespace, and everything afterwards will use the normal $IFS.

Side note: using the shell's word splitting means you won't notice
empty elements as in "PATH=/foo::/bar".  So it won't exactly match the
behavior of the shell's/exec*p's $PATH search for programs, which
treats the empty element like ".".

> But just to make sure that the modified assignment did what I intended.. 
> I had also added an "echo $IFS" immediately after and this did not give 
> me the expected result.

"echo $IFS" should always give an empty line, because the characters in
$IFS are treated as whitespace for word splitting.  Do this instead:
echo "$IFS"
Quoting will prevent word splitting and globbing for the expanded
value.  This applies to variable expansion, command substitution, and
all other transformations described under "EXPANSION" in the man page.
Of course, trailing whitespace won't typically be visible in a
terminal window, so to make the end points visible: echo "<$IFS>"
Or perhaps: echo "$IFS" | cat -vte

If you see a colon, and not an empty line, for the unquoted expansion,
then (just a guess) that might be what the note about the security fix
was referring to.

> 1. The bash man page describes IFS as a special variable. What does the 
> "special" imply?

That it's used internally by the shell - specifically, to determine
the word splitting delimiter characters.

> 2. Is it good bash programming practice to modify, save, and restore the 
> contents of the IFS variable? It looks like a powerful, elegant 
> technique but likely to be a source of later headaches if used incorrectly..

If you're going to use unquoted expansion to split a string, then
that's usually the way to do it.  Quoting all expansions that aren't
specifically meant for splitting/globbing is also good practice.

> 3. The bash man page does not mention IFS explicitly when describing the 
> "for" construct. Am I correct in assuming that "for" uses the contents 
> of the IFS variable to parse a character string into words?

It's not about "for"; it's about unquoted expansions.  The unquoted
expansion in this case just happens to produce a list of items for the
loop to iterate over.


paul




reply via email to

[Prev in Thread] Current Thread [Next in Thread]