[comp.unix.shell] Problem with sh/ksh quoting

kherron@ms.uky.edu (Kenneth Herron) (10/31/90)

I'm having a problem with quoting in shell scripts, exemplified by
the following:

line="this is 'a test'"

for word in $line
do
	echo $word
done

I *want* it to produce:
this
is
a test

but it produces:
this
is
'a
test'

I've tried some variations:
line='this is ''a test'''

line="this is \'a test\'"

temp='a test'
line="this is $temp"

temp='a test'
line="this is '$temp'"

and so on, but either the final set of quotes are stripped out, or not
recognized (as above), or the temp variable isn't expanded, or just about
anything but what I want.  Eval didn't seem to help, nor did quoting the
space within 'a test'.  Does anyone know how to accomplish this?

(BTW, what I'm REALLY trying to do is set options to a command (less) 
where one of the options (the -P prompt option) takes an argument with
spaces.)

Kenneth Herron

pfalstad@drops.Princeton.EDU (Paul John Falstad) (11/01/90)

In article <16289@s.ms.uky.edu> kherron@ms.uky.edu (Kenneth Herron) writes:
>line="this is 'a test'"
>
>for word in $line
>do
>	echo $word
>done
>
>I *want* it to produce:
>this
>is
>a test

Try something like this:

$ IFS='
'
$ line='this
is
a test'
$ for i in $line
> do
> echo $i
> done
this
is
a test
$ ...


--
Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD
I would bring back hanging, and go into rope.  I would cut off the more
disreputable parts of the body and use the space for playing fields.

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (11/01/90)

In article <16289@s.ms.uky.edu> kherron@ms.uky.edu (Kenneth Herron) writes:
>I'm having a problem with quoting in shell scripts, exemplified by
>the following:
>
>line="this is 'a test'"
>
>for word in $line
>do
>	echo $word
>done
>
>I *want* it to produce:
>this
>is
>a test

For ksh, you can use an array:

	$ set -A  line  this is 'a test'
	$ for word in "${line[@]}"
	$ do
	$   echo $word
	$ done
	this
	is
	a test

Watch out though, in early version of ksh (earlier than ksh 11/16/88a)
using set -A will ALSO clobber your positional parameters ($1, $2, $*, $@)
and set them to the contents of your array in addition to setting your array.
If you have such a version of ksh you MAY have to do:

	$ set -A argv "$@"                         ## save $@
	$ set -A  line  this is 'a test'           ## set my array
	$ set --  "$@"                             ## restore $@

For sh, there are all sorts of tricks you can use but they are just that,
tricks. In the Bourne shell only "$@" preserves whitespace/IFS characters
in its arguments (whereas "${array[@]}" preserves whitespace/IFS characters
in ksh arrays).

A common Bourne shell trick is:

	$ line1=this
	$ line2=is
	$ line3='a test'

	$ i=0
	$ while [ $i -lt 3 ] ; do
	$   i=`expr $i + 1`
	$   eval echo \$line$i
	$ done
	this
	is
	a test

There are other "obscure" Bourne shell trick as well!
Hope this helps!
______________________ "And miles to go before I sleep." ______________________
 Brad Appleton           brad@ssd.csd.harris.com       Harris Computer Systems
                             uunet!hcx1!brad           Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

tif@doorstop.austin.ibm.com (Paul Chamberlain) (11/02/90)

In article <16289@s.ms.uky.edu> kherron@ms.uky.edu (Kenneth Herron) writes:
>	line="this is 'a test'"
>	...
>I *want* it to produce:
>this
>is
>a test

Nice challenge.  I finally got it, and you don't have to change things
as dramatically as other people had posted.  My method works like this:

	line='this is "a test"'
	eval set -- $line
	for word
	do
		echo $word
	done

I couldn't figure out how to get eval to work like this:

	eval for word in $line
	...

I'm gonna start calling myself "The Shell Answer-man".

Paul Chamberlain | I do NOT represent IBM.     tif@doorstop, sc30661 at ausvm6
512/838-7008     | ...!cs.utexas.edu!ibmchs!auschs!doorstop.austin.ibm.com!tif

qpliu@phoenix.princeton.edu (q.p.liu) (11/02/90)

In article <4101@awdprime.UUCP> tif@doorstop.austin.ibm.com (Paul Chamberlain) writes:
>
>I couldn't figure out how to get eval to work like this:
>
>	eval for word in $line
>	...
>
you hafta do this:

	eval "for word in $line; do echo \$word; done"

works for bash and sh, don't have a ksh to try it on.

>I'm gonna start calling myself "The Shell Answer-man".

--
Don't reply to the address in the From field, it may be wrong.
Don't reply to the address in the Reply-to field, it may be wrong.
Don't reply to the address in the .sig, it may be wrong.

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (11/03/90)

In article <4101@awdprime.UUCP> tif@doorstop.austin.ibm.com (Paul Chamberlain) writes:
>In article <16289@s.ms.uky.edu> kherron@ms.uky.edu (Kenneth Herron) writes:
>>	line="this is 'a test'"
>>	...
>>I *want* it to produce:
>>this
>>is
>>a test
>
>Nice challenge.  I finally got it, and you don't have to change things
>as dramatically as other people had posted.  My method works like this:
>
>	line='this is "a test"'
>	eval set -- $line
>	for word
>	do
>		echo $word
>	done
>
This is fine and dandy except that you have now LOST your positional parameters
(and if you are in a script - you may still need them). Furthermore - saving
your parameters first by doing something like:

	save_args="$*"

Is no help because now you will need to exercise some even fancier footwork to
get the parameters back the way they were if any contained IFS characters.

Like I said before - if you have the Korn shell, this is all *very* simple
if you create an array using "set -A" (or "set +A") and iterate your for-loop
based on "$array[@}" (the quotes are needed here). If you are using the
Bourne shell AND no longer need your postional parameters, then the method
described above will suit you just fine - If you still need the positional
positonal parameters (with sh) though - you'd better find another way (two
have been posted already).

______________________ "And miles to go before I sleep." ______________________
 Brad Appleton           brad@ssd.csd.harris.com       Harris Computer Systems
                             uunet!hcx1!brad           Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (11/03/90)

In article <1452@travis.csd.harris.com> brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes:
>Like I said before - if you have the Korn shell, this is all *very* simple
>if you create an array using "set -A" (or "set +A") and iterate your for-loop
>based on "$array[@}" (the quotes are needed here). If you are using the

OOPS - bad typing! that should read :

	"${array[@]}"

and NOT

	"$array[@}"

for obvious reasons!!!
______________________ "And miles to go before I sleep." ______________________
 Brad Appleton           brad@ssd.csd.harris.com       Harris Computer Systems
                             uunet!hcx1!brad           Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~