script arguments with spaces

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

script arguments with spaces

Chris Muller-4
To get the first argument to the Smalltalk startup script we have:

   Smalltalk getSystemAttribute: 3

but does anyone know whether this can be an argument with spaces?

I actually want to allow the Linux user to specify a chunk of code
(which contains spaces) on the command-line.

I tried enclosing it in ticks, but Squeak still loaded each
system-attribute into its own slot.  Interestingly, it did not include
the beginning or ending tick.

So, it looks like I could assemble all of the pieces, separatedBy:
Character space, but that would limit the chunk to 997 "words"..

Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Eliot Miranda-2


On Thu, Oct 7, 2010 at 11:49 AM, Chris Muller <[hidden email]> wrote:
To get the first argument to the Smalltalk startup script we have:

  Smalltalk getSystemAttribute: 3

but does anyone know whether this can be an argument with spaces?

Of course.  Try it and see.  This is a shell issue.  What's the syntax to supply an arg containing spaces.  On Unix there are two^H^H^Hthree^H^H^H^H^Hfour ways.  Escape spaces with back slashes, use IFS to make space a non-separator and separate words using e.g. TAB (I think this works), surround the argument with single quotes or surround the arg with double quotes.


I actually want to allow the Linux user to specify a chunk of code
(which contains spaces) on the command-line.

I tried enclosing it in ticks, but Squeak still loaded each
system-attribute into its own slot.  Interestingly, it did not include
the beginning or ending tick.

So, it looks like I could assemble all of the pieces, separatedBy:
Character space, but that would limit the chunk to 997 "words"..




Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Chris Muller-3
> Of course.  Try it and see.  This is a shell issue.  What's the syntax to
> supply an arg containing spaces.  On Unix there are
> two^H^H^Hthree^H^H^H^H^Hfour ways.  Escape spaces with back slashes, use IFS
> to make space a non-separator and separate words using e.g. TAB (I think
> this works), surround the argument with single quotes or surround the arg
> with double quotes.

Right I did try all of those things of course (except adjusting IFS),
but it appears that Squeak puts its own interpretation onto these
arguments differently from the shell.  IOW, Squeak appears to be doing
a simple subStrings operation regardless of escape-characters when
loading up the systemAttribute array...  For example:

  st '1000 factorial'    <----- Squeak gets 2 args, '1000' and 'factorial'
  st "1000\ factorial"    <----- Squeak gets 2 args, '1000\' and 'factorial'

Strings are a challenge because the shell does not allow single-ticks
inside of single-ticks, but one can use Symbols:

  st '#hello asString asUppercase'   <--------- Squeak gets 3 args...

My goal is to deliver a "Smalltalk command-line".  I did find that
your stdin works, so I can do:

  st <<printit
'hello' asUppercase
printit

works.  :)


>>
>> I actually want to allow the Linux user to specify a chunk of code
>> (which contains spaces) on the command-line.
>>
>> I tried enclosing it in ticks, but Squeak still loaded each
>> system-attribute into its own slot.  Interestingly, it did not include
>> the beginning or ending tick.
>>
>> So, it looks like I could assemble all of the pieces, separatedBy:
>> Character space, but that would limit the chunk to 997 "words"..
>>
>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Bert Freudenberg
Squeak does it right. I suspect your "st" script is broken.

- Bert -


On 08.10.2010, at 09:44, Chris Muller wrote:

>> Of course.  Try it and see.  This is a shell issue.  What's the syntax to
>> supply an arg containing spaces.  On Unix there are
>> two^H^H^Hthree^H^H^H^H^Hfour ways.  Escape spaces with back slashes, use IFS
>> to make space a non-separator and separate words using e.g. TAB (I think
>> this works), surround the argument with single quotes or surround the arg
>> with double quotes.
>
> Right I did try all of those things of course (except adjusting IFS),
> but it appears that Squeak puts its own interpretation onto these
> arguments differently from the shell.  IOW, Squeak appears to be doing
> a simple subStrings operation regardless of escape-characters when
> loading up the systemAttribute array...  For example:
>
>  st '1000 factorial'    <----- Squeak gets 2 args, '1000' and 'factorial'
>  st "1000\ factorial"    <----- Squeak gets 2 args, '1000\' and 'factorial'
>
> Strings are a challenge because the shell does not allow single-ticks
> inside of single-ticks, but one can use Symbols:
>
>  st '#hello asString asUppercase'   <--------- Squeak gets 3 args...
>
> My goal is to deliver a "Smalltalk command-line".  I did find that
> your stdin works, so I can do:
>
>  st <<printit
> 'hello' asUppercase
> printit
>
> works.  :)
>
>
>>>
>>> I actually want to allow the Linux user to specify a chunk of code
>>> (which contains spaces) on the command-line.
>>>
>>> I tried enclosing it in ticks, but Squeak still loaded each
>>> system-attribute into its own slot.  Interestingly, it did not include
>>> the beginning or ending tick.
>>>
>>> So, it looks like I could assemble all of the pieces, separatedBy:
>>> Character space, but that would limit the chunk to 997 "words"..
>>>
>>
>>
>>
>>
>>
>


Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Eliot Miranda-2
In reply to this post by Chris Muller-3
Hi Chris,

On Fri, Oct 8, 2010 at 9:44 AM, Chris Muller <[hidden email]> wrote:
> Of course.  Try it and see.  This is a shell issue.  What's the syntax to
> supply an arg containing spaces.  On Unix there are
> two^H^H^Hthree^H^H^H^H^Hfour ways.  Escape spaces with back slashes, use IFS
> to make space a non-separator and separate words using e.g. TAB (I think
> this works), surround the argument with single quotes or surround the arg
> with double quotes.

Right I did try all of those things of course (except adjusting IFS),
but it appears that Squeak puts its own interpretation onto these
arguments differently from the shell.  IOW, Squeak appears to be doing
a simple subStrings operation regardless of escape-characters when
loading up the systemAttribute array...  For example:

 st '1000 factorial'    <----- Squeak gets 2 args, '1000' and 'factorial'
 st "1000\ factorial"    <----- Squeak gets 2 args, '1000\' and 'factorial'

Strings are a challenge because the shell does not allow single-ticks
inside of single-ticks, but one can use Symbols:

 st '#hello asString asUppercase'   <--------- Squeak gets 3 args...

My goal is to deliver a "Smalltalk command-line".  I did find that
your stdin works, so I can do:

 st <<printit
'hello' asUppercase
printit

works.  :)


    Bert is very probably right.  If you're suing bourne/bash then look up the difference between $*, "$*", $@ and "$@".  To preserve spaces you need to use $@/"$@" (depending on context" *not* $*.  Also within your script you can use IFS to prevent space being a separator.

HTH
Eliot



>>
>> I actually want to allow the Linux user to specify a chunk of code
>> (which contains spaces) on the command-line.
>>
>> I tried enclosing it in ticks, but Squeak still loaded each
>> system-attribute into its own slot.  Interestingly, it did not include
>> the beginning or ending tick.
>>
>> So, it looks like I could assemble all of the pieces, separatedBy:
>> Character space, but that would limit the chunk to 997 "words"..
>>
>
>
>
>
>




Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

K K Subbu
On Saturday 09 Oct 2010 4:06:37 am Eliot Miranda wrote:
>     Bert is very probably right.  If you're suing bourne/bash then look up
> the difference between $*, "$*", $@ and "$@".  To preserve spaces you need
> to use $@/"$@" (depending on context" not $*.  Also within your script you
> can use IFS to prevent space being a separator.
‌$@ always uses space as word separator while $* uses the first letter of IFS
variable. Otherwise they are the same.‌ Smalltalk uses spaces for separator so
$@ will do.

Subbu

Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Eliot Miranda-2


On Fri, Oct 8, 2010 at 9:02 PM, K. K. Subramaniam <kksubbu.ml@gmail.com> wrote:
On Saturday 09 Oct 2010 4:06:37 am Eliot Miranda wrote:
>     Bert is very probably right.  If you're suing bourne/bash then look up
> the difference between $*, "$*", $@ and "$@".  To preserve spaces you need
> to use $@/"$@" (depending on context" not $*.  Also within your script you
> can use IFS to prevent space being a separator.
‌$@ always uses space as word separator while $* uses the first letter of IFS
variable. Otherwise they are the same.‌ Smalltalk uses spaces for separator so
$@ will do.


No.  $@ expands to the argument list as supplied to the current command:

       *      Expands  to  the positional parameters, starting from one.  When
              the expansion occurs within double quotes, it expands to a  sin-
              gle word with the value of each parameter separated by the first
              character of the IFS special variable.  That is, "$*" is equiva-
              lent to "$1c$2c...", where c is the first character of the value
              of the IFS variable.  If IFS is unset, the parameters are  sepa-
              rated  by  spaces.   If  IFS  is null, the parameters are joined
              without intervening separators.
       @      Expands to the positional parameters, starting from  one.   When
              the  expansion  occurs  within  double  quotes,  each  parameter
              expands to a separate word.  That is, "$@" is equivalent to "$1"
              "$2"  ... 

So when invoking a command from within a shell wrapper one should use "$@" to pass on the parameters as this preserves whitespace within parameters.
e.g.
-----------8<----------- printargs -----------8<-----------
#!/bin/sh
while [ $# -gt 0 ]; do
    echo "    ""$1"
    shift
done
-----------8<----------- wrapper -----------8<-----------
#!/bin/sh
echo '$*'
printargs $*  
echo '"$*"'
printargs "$*"
echo '$@'
printargs $@
echo '"$@"'
printargs "$@"
-----------8<-----------
$ wrapper "hello world" hello world
prints:
$*
    hello
    world
    hello
    world
"$*"
    hello world hello world
$@
    hello
    world
    hello
    world
"$@"
    hello world
    hello
    world


HTH 

Subbu




printargs (86 bytes) Download Attachment
wrapper (150 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Eliot Miranda-2


On Fri, Oct 8, 2010 at 10:09 PM, Eliot Miranda <[hidden email]> wrote:


On Fri, Oct 8, 2010 at 9:02 PM, K. K. Subramaniam <kksubbu.ml@gmail.com> wrote:
On Saturday 09 Oct 2010 4:06:37 am Eliot Miranda wrote:
>     Bert is very probably right.  If you're suing bourne/bash then look up
> the difference between $*, "$*", $@ and "$@".  To preserve spaces you need
> to use $@/"$@" (depending on context" not $*.  Also within your script you
> can use IFS to prevent space being a separator.
‌$@ always uses space as word separator while $* uses the first letter of IFS
variable. Otherwise they are the same.‌ Smalltalk uses spaces for separator so
$@ will do.


No.  $@ expands to the argument list as supplied to the current command:


I should have written
     "$@" expands to the argument list as supplied to the current command:
 

       *      Expands  to  the positional parameters, starting from one.  When
              the expansion occurs within double quotes, it expands to a  sin-
              gle word with the value of each parameter separated by the first
              character of the IFS special variable.  That is, "$*" is equiva-
              lent to "$1c$2c...", where c is the first character of the value
              of the IFS variable.  If IFS is unset, the parameters are  sepa-
              rated  by  spaces.   If  IFS  is null, the parameters are joined
              without intervening separators.
       @      Expands to the positional parameters, starting from  one.   When
              the  expansion  occurs  within  double  quotes,  each  parameter
              expands to a separate word.  That is, "$@" is equivalent to "$1"
              "$2"  ... 

So when invoking a command from within a shell wrapper one should use "$@" to pass on the parameters as this preserves whitespace within parameters.
e.g.
-----------8<----------- printargs -----------8<-----------
#!/bin/sh
while [ $# -gt 0 ]; do
    echo "    ""$1"
    shift
done
-----------8<----------- wrapper -----------8<-----------
#!/bin/sh
echo '$*'
printargs $*  
echo '"$*"'
printargs "$*"
echo '$@'
printargs $@
echo '"$@"'
printargs "$@"
-----------8<-----------
$ wrapper "hello world" hello world
prints:
$*
    hello
    world
    hello
    world
"$*"
    hello world hello world
$@
    hello
    world
    hello
    world
"$@"
    hello world
    hello
    world


HTH 

Subbu




Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Chris Muller-3
In reply to this post by Bert Freudenberg
Hm, it looks like you are right.  When I pass the argument directly to squeak:

  squeak my.image my.script 'hello world' &

and 'hello world' came in as a single-argument.  So I've got some bashing to do.

Thanks, and sorry for the false alarm.

 - Chris

PS - is there a Linux "best practice" or overall preference regarding
command-line arguments vs. stdin?  stdin would allow redirection of
Smalltalk scripts, as well as the convenience of raw stream input via
the keyboard (e.g., not having to worry about escape chars), so I'm
leaning that way...


On Fri, Oct 8, 2010 at 4:10 PM, Bert Freudenberg <[hidden email]> wrote:

> Squeak does it right. I suspect your "st" script is broken.
>
> - Bert -
>
>
> On 08.10.2010, at 09:44, Chris Muller wrote:
>
>>> Of course.  Try it and see.  This is a shell issue.  What's the syntax to
>>> supply an arg containing spaces.  On Unix there are
>>> two^H^H^Hthree^H^H^H^H^Hfour ways.  Escape spaces with back slashes, use IFS
>>> to make space a non-separator and separate words using e.g. TAB (I think
>>> this works), surround the argument with single quotes or surround the arg
>>> with double quotes.
>>
>> Right I did try all of those things of course (except adjusting IFS),
>> but it appears that Squeak puts its own interpretation onto these
>> arguments differently from the shell.  IOW, Squeak appears to be doing
>> a simple subStrings operation regardless of escape-characters when
>> loading up the systemAttribute array...  For example:
>>
>>  st '1000 factorial'    <----- Squeak gets 2 args, '1000' and 'factorial'
>>  st "1000\ factorial"    <----- Squeak gets 2 args, '1000\' and 'factorial'
>>
>> Strings are a challenge because the shell does not allow single-ticks
>> inside of single-ticks, but one can use Symbols:
>>
>>  st '#hello asString asUppercase'   <--------- Squeak gets 3 args...
>>
>> My goal is to deliver a "Smalltalk command-line".  I did find that
>> your stdin works, so I can do:
>>
>>  st <<printit
>> 'hello' asUppercase
>> printit
>>
>> works.  :)
>>
>>
>>>>
>>>> I actually want to allow the Linux user to specify a chunk of code
>>>> (which contains spaces) on the command-line.
>>>>
>>>> I tried enclosing it in ticks, but Squeak still loaded each
>>>> system-attribute into its own slot.  Interestingly, it did not include
>>>> the beginning or ending tick.
>>>>
>>>> So, it looks like I could assemble all of the pieces, separatedBy:
>>>> Character space, but that would limit the chunk to 997 "words"..
>>>>
>>>
>>>
>>>
>>>
>>>
>>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

Eliot Miranda-2


On Sat, Oct 9, 2010 at 10:54 AM, Chris Muller <[hidden email]> wrote:
Hm, it looks like you are right.  When I pass the argument directly to squeak:

 squeak my.image my.script 'hello world' &

and 'hello world' came in as a single-argument.  So I've got some bashing to do.

You need to use "$@", not $@, $* or "$*".  See the squeak scripts in the Cog linux VM for an example.

#!/bin/sh
BIN=`/usr/bin/dirname $0`/lib/squeak/3.9-7
# At least on linux LD_LIBRARY_PATH's components must be absolute path names
case "$BIN" in
/*) PLUGINS="$BIN";;
*) PLUGINS="`pwd`/$BIN"
esac
# prepending is less flexible but safer because it ensures we find the plugins
# in the same directory as the VM.
LD_LIBRARY_PATH=$PLUGINS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} exec "$BIN/squeak" "$@"


Thanks, and sorry for the false alarm.

 - Chris

PS - is there a Linux "best practice" or overall preference regarding
command-line arguments vs. stdin?  stdin would allow redirection of
Smalltalk scripts, as well as the convenience of raw stream input via
the keyboard (e.g., not having to worry about escape chars), so I'm
leaning that way...

Since Squeak hasn't been used that much with stdio I would expect there not to be any best practices.  Instead you should just go ahead and explore.  I think the point of using stdin is that it allows interactive experimentation.  In developing a bootstrap from a kernel image tis will have its uses.  Being able to write pipelined commands in Squeak is fun but arguably one needs a much better file interface to make this compelling.  


On Fri, Oct 8, 2010 at 4:10 PM, Bert Freudenberg <[hidden email]> wrote:
> Squeak does it right. I suspect your "st" script is broken.
>
> - Bert -
>
>
> On 08.10.2010, at 09:44, Chris Muller wrote:
>
>>> Of course.  Try it and see.  This is a shell issue.  What's the syntax to
>>> supply an arg containing spaces.  On Unix there are
>>> two^H^H^Hthree^H^H^H^H^Hfour ways.  Escape spaces with back slashes, use IFS
>>> to make space a non-separator and separate words using e.g. TAB (I think
>>> this works), surround the argument with single quotes or surround the arg
>>> with double quotes.
>>
>> Right I did try all of those things of course (except adjusting IFS),
>> but it appears that Squeak puts its own interpretation onto these
>> arguments differently from the shell.  IOW, Squeak appears to be doing
>> a simple subStrings operation regardless of escape-characters when
>> loading up the systemAttribute array...  For example:
>>
>>  st '1000 factorial'    <----- Squeak gets 2 args, '1000' and 'factorial'
>>  st "1000\ factorial"    <----- Squeak gets 2 args, '1000\' and 'factorial'
>>
>> Strings are a challenge because the shell does not allow single-ticks
>> inside of single-ticks, but one can use Symbols:
>>
>>  st '#hello asString asUppercase'   <--------- Squeak gets 3 args...
>>
>> My goal is to deliver a "Smalltalk command-line".  I did find that
>> your stdin works, so I can do:
>>
>>  st <<printit
>> 'hello' asUppercase
>> printit
>>
>> works.  :)
>>
>>
>>>>
>>>> I actually want to allow the Linux user to specify a chunk of code
>>>> (which contains spaces) on the command-line.
>>>>
>>>> I tried enclosing it in ticks, but Squeak still loaded each
>>>> system-attribute into its own slot.  Interestingly, it did not include
>>>> the beginning or ending tick.
>>>>
>>>> So, it looks like I could assemble all of the pieces, separatedBy:
>>>> Character space, but that would limit the chunk to 997 "words"..
>>>>
>>>
>>>
>>>
>>>
>>>
>>
>
>
>




Reply | Threaded
Open this post in threaded view
|

Re: script arguments with spaces

K K Subbu
In reply to this post by Eliot Miranda-2
On Saturday 09 Oct 2010 10:39:16 am Eliot Miranda wrote:
> > ‌$@ always uses space as word separator while $* uses the first letter of
> > IFS
> > variable. Otherwise they are the same.‌ Smalltalk uses spaces for
> > separator so
> > $@ will do.
>
> No.  $@ expands to the argument list as supplied to the current command:
My statement was ambiguous. Your clarification and example is much clearer, as
the following reveals:
$ IFS=: wrapper "hello world" hello world
<snip>
"$*"
    hello world:hello:world
<snip>
"$@"
    hello world
    hello
    world

For programs which use : as word separator, "$*" will pass all its arguments
as a *single argument* separated by colon so that the program itself can split
them into separate arguments. For programs like squeakvm that don't have
argument parsers "$@" will pass them as space-separated *arguments*. In both
cases, spaces within arguments enclosed by quotes will be preserved.

Thanks .. Subbu