|
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]
|
|
| 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".
|
|
|
|
|