Unix Shell - simple "for loop"

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > November 2006 > simple "for loop"





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author simple "for loop"
Christian Pontesegger

2006-11-26, 1:16 pm

Hi,

I was experimenting with a for loop to iterate over files using spaces
within the filename:


FOO="\"hello world\" \"this is a test\""
for arg in ${FOO}; do
echo ${arg}
done


what I expected were 2 lines:
"hello world"
"this is a test"


but I actually get
"hello
world"
"this
is
a
test"


what is the correct syntax that my quotes are handles correctly?

thanks
Christian
Janis Papanagnou

2006-11-26, 1:16 pm

Christian Pontesegger wrote:
> Hi,
>
> I was experimenting with a for loop to iterate over files using spaces
> within the filename:
>
>
> FOO="\"hello world\" \"this is a test\""
> for arg in ${FOO}; do
> echo ${arg}
> done


Use arrays, if possible...

FOO=( "hello world" "this is a test" )
for arg in "${FOO[@]}"; do
echo ${arg}
done

Or use positional parameter...

set - "hello world" "this is a test"
for arg; do
echo ${arg}
done

>
>
> what I expected were 2 lines:
> "hello world"
> "this is a test"
>
>
> but I actually get
> "hello
> world"
> "this
> is
> a
> test"
>
>
> what is the correct syntax that my quotes are handles correctly?


Avoid fiddling with quotes, if possible.

Janis

>
> thanks
> Christian

Michael Paoli

2006-11-26, 7:18 pm

Christian Pontesegger wrote:
> I was experimenting with a for loop to iterate over files using spaces
> within the filename:
> FOO="\"hello world\" \"this is a test\""
> for arg in ${FOO}; do
> echo ${arg}
> done
> what I expected were 2 lines:
> "hello world"
> "this is a test"
> but I actually get
> "hello
> world"
> "this
> is
> a
> test"
> what is the correct syntax that my quotes are handles correctly?


And where are files being used here (other than stdin/stdout/stderr)?
Nevertheless, maybe this is closer to what you're looking for and
expecting:
$ >'"hello world"'
$ >'"this is a test"'
$ ls -1
"hello world"
"this is a test"
$ for arg in *; do echo "$arg"; done; unset arg
"hello world"
"this is a test"
$
${FOO}, and likewise $FOO will ordinarily be split into "words" by the
shell, whereas "${FOO}" and likewise "$FOO" will undergo parameter
substitution, but will then remain as a single string/argument.

"You will want to study sh(1) long and hard."
- UNIX PROGRAMMER'S MANUAL, Seventh Edition, January, 1979, Volume 1,
INTRODUCTION TO VOLUME 1

Chris F.A. Johnson

2006-11-26, 7:18 pm

On 2006-11-26, Christian Pontesegger wrote:
> Hi,
>
> I was experimenting with a for loop to iterate over files using spaces
> within the filename:
>
>
> FOO="\"hello world\" \"this is a test\""
> for arg in ${FOO}; do
> echo ${arg}
> done
>
>
> what I expected were 2 lines:
> "hello world"
> "this is a test"
>
> but I actually get
> "hello
> world"
> "this
> is
> a
> test"
>
>
> what is the correct syntax that my quotes are handles correctly?


eval "for arg in ${FOO}; do
echo \${arg}
done"

Or:

eval "printf \"%s\n\" $FOO"


--
Chris F.A. Johnson, author <http://cfaj.freeshell.org/shell>
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)
===== My code in this post, if any, assumes the POSIX locale
===== and is released under the GNU General Public Licence
Kaz Kylheku

2006-11-28, 7:29 am

Christian Pontesegger wrote:
> Hi,
>
> I was experimenting with a for loop to iterate over files using spaces
> within the filename:
>
>
> FOO="\"hello world\" \"this is a test\""


You can tell right away that this isn't going to work.

The POSIX shell processes quotes as it reads the script source code:
they are part of its syntax which means "the script material between
these quotes is not subject to word splitting". What you have done here
is embed the quotes into the string data by escaping them. That data
isn't code, and so these quotes won't have their quoting effect
(preventing word splitting) unless you coax the shell into scanning
that data as shell source code. That is done by eval or a moral
equivalent thereof (such as feeding the string to a nested shell
invocation).

> for arg in ${FOO}; do


The $FOO is unquoted here, and so its expansion is subject to word
splitting. The shell won't scan for quotes in the data itself; the
quotes are just ordinary non-whitespace characters in the string. So
the string breaks up into the words {"hello} {world"} {"this} {is} {a}
{test"}.

> what is the correct syntax that my quotes are handles correctly?


You can bring in eval:

eval "for arg in $FOO ; do echo \$arg ; done"

Here, we are passing the entire for loop as a string of source code to
eval. But it's not a fixed string; it contains $FOO which is
substituted into the string, quotes and all, producing this code:

for arg in "hello world" "this is a test" ; do echo $arg ; done.

This is what is passed to eval, and so of course it has the right
effect.

Note how we protected the dollar sign in front of $arg, because we want
its expansion to happen at a different time, not before the eval. We
have effectively done a kind of macro preprocessing to generate the
code we want.

Kaz Kylheku

2006-11-28, 7:29 am

Michael Paoli wrote:
> "You will want to study sh(1) long and hard."
> - UNIX PROGRAMMER'S MANUAL, Seventh Edition, January, 1979, Volume 1,
> INTRODUCTION TO VOLUME 1


That must have been a typo for "have to".

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com