list="foo -opt1:bar -opt2:baz -opt3"
origIFS=$IFS
IFS=':'
for x in $list; do
# reset IFS here because commands in the loop rely on IFS being the default
IFS=$origIFS
echo $x
# more stuff in here that relies on IFS being the default
done
# need to reset IFS here in case list is empty and for loop not executed
IFS=$origIFS
I was very surprised that the following did not work. The error
message I get is "do unexpected".
IFS=':' for x in $list; do
echo $x
done
I don't think it matters, but just in case, my system is:
% uname -a
SunOS seurat 5.6 Generic_105181-03 sun4u sparc
% which sh
sh is /usr/bin/sh
Thanks,
Fred Wheeler
--
Fred Wheeler
wheeler (at) cipr.rpi.edu
www.cipr.rpi.edu/wheeler
I'm not sure if I unterstand what you want to do. I expect the
following: first x="foo -opt1", second x="bar -opt2", ...
What about replacing all spaces first by perhaps "+" and all ":" by
sopaces. In your loop, you can than replace the "+" by space. So you
don't have to change your IFS.
for y in `echo $list | sed -e 's/ /+/g' -e 's/:/ /g'`; do
x=`echo $y | sed 's/+/ /g'`
echo $x
done
Angela
foo -opt1
bar -opt2
baz -opt3
It just seems kludgy to have to set and restore IFS the way I do. I'm
looking for a simple way to get IFS-: applied to the $list variable
expansion in the for loop and nowhere else.
whe...@cipr.no_spam.rpi.edu (Frederick W. Wheeler) writes:
> list="foo -opt1:bar -opt2:baz -opt3"
>
> origIFS=$IFS
> IFS=':'
> for x in $list; do
> # reset IFS here because commands in the loop rely on IFS being the default
> IFS=$origIFS
> echo $x
> # more stuff in here that relies on IFS being the default
> done
> # need to reset IFS here in case list is empty and for loop not executed
> IFS=$origIFS
Thanks,
You're sure right about kludgy, but the only thing I can suggest (I do
this not infrequently myself) is to replace the argument list:
origIFS=$IFS
set $list
IFS=$origIFS
for x
do ...
If you can't discard the actual argument list at this point, and your shell
doesn't have array capabilities anywhere else, the only other approaches I
can think of are even worse. You could get something to work along the lines
of replace : with newlines, and replace "for x" with "while read x", but it
would be no great step forward.
| I was very surprised that the following did not work. The error
| message I get is "do unexpected".
|
| IFS=':' for x in $list; do
| echo $x
| done
That syntax is to my knowledge only valid for assignment of environment
variables for a command statement, which "for" is not.
Donn Cave, University Computing Services, University of Washington
do...@u.washington.edu
Depending on whether or not you need to access the pre-existing argument
list at or after this point in the script, you might be able to use:
origIFS="$IFS"
IFS=':'
set -- $list
IFS="$origIFS"
for x; do
echo $x
# more stuff in here that relies on IFS being the default
done
# more stuff here that relies on IFS being the default
Not a huge win in terms of complexity, but at least all the IFS
games are localized in one place, rather than scattered hither
and yon.
--Ken Pizzini
> | I was very surprised that the following did not work. The error
> | message I get is "do unexpected".
> |
> | IFS=':' for x in $list; do
> | echo $x
> | done
>
> That syntax is to my knowledge only valid for assignment of environment
> variables for a command statement, which "for" is not.
I just happened to think of this off the top of my head. It seems to work.
for f in `IFS=: ; set -- $PATH ; echo "$@"`
do
echo $f
done
I'm not sure this counts as better or worse than any of the other
solutions I've seen. It does avoid the problem of saving/restoring
IFS, at the expense of a subshell.
Dale.
My favorite scripting idiom for the above situation is:
IFS=: eval "set -- \$list; IFS='$IFS'" # "list" is your colon-delimited list var
No temporary variables holding IFS; no setting and resetting of
IFS per a scope of code; no unnecessary processes or process
environments or external software.... Now that the hard work is
done:
for list_element
do # do anything here; IFS is always set to default ...
done
-Brian
> My favorite scripting idiom for the above situation is:
> IFS=: eval "set -- \$list; IFS='$IFS'"
> No temporary variables holding IFS; no setting and resetting of
> IFS per a scope of code; no unnecessary processes or process
> environments or external software....
Hey, I like this one. Mine had other problems to, I think, if the
various fields happened to contain whitespace.
Why do you need the IFS assignment in the eval string though? It
seems to work fine without it for me, as in
IFS=: eval 'set -- $list'
Dale.
I didn't write any of that, contrary to the apparent attribution.
The problem with the suggested usage is that the output of the `` gets
split, again, this time on white space. If there is any white space
in there, you lose. /etc/passwd is a better example of this than PATH.
| My favorite scripting idiom for the above situation is:
|
| IFS=: eval "set -- \$list; IFS='$IFS'" # "list" is your colon-delimited list var
|
| No temporary variables holding IFS; no setting and resetting of
| IFS per a scope of code; no unnecessary processes or process
| environments or external software.... Now that the hard work is
| done:
OK, but it seems to me like a lot of trouble to avoid a temporary variable,
compared to the IFS based approach the original poster was already using.
I guess there's always going to be some difference of opinion on questions
maintainability and elegance, maybe I react too strongly to "eval".
Thank you. For every submission of a good idea I have made to
c.u.s., I assure you I have received three from it!
> Why do you need the IFS assignment in the eval string though? It
> seems to work fine without it for me, as in
> IFS=: eval 'set -- $list'
Technically, one does not need to include the "eval" or for that
matter the reassignment of the IFS variable; however, the side-efect
of the above will be to change the IFS variable--and the scripting
idiom I submitted exists to transparently parse field delimiters
without making these. As a scripting idiom, one merely need to
"substitute the parameters" and not worry about consequences.
Command verbosity is made up by benignity.
The "eval" is there for the necessity of resetting the IFS value
to the original value_and_ performing a "set ..." _in the same
instruction_.
P.S. Unfortunately the above will not work as written in bash, as
Chet Ramey has not seen fit to implement the documented feature "special
shell builtins" as he cannot think of why anyone would what to use
this facility. Hmmm.
-Brian
>P.S. Unfortunately the above will not work as written in bash, as
>Chet Ramey has not seen fit to implement the documented feature "special
>shell builtins" as he cannot think of why anyone would what to use
>this facility. Hmmm.
Don't be deliberately disingenuous. This feature is available when
bash is in posix mode, and is documented.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
( ``Discere est Dolere'' -- chet)
Chet Ramey, Case Western Reserve University Internet: ch...@po.CWRU.Edu
You could cheat, and do something like ;
IFS=":"
set -A array1 $list
for x in ${array1[*]}
do
echo x
done
IFS=" "
Cheers
davey
>
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own