Ash eval wierdness

2011-05-25 Thread Nigel Hathaway
I'm trying to import a set of variables from a file containing assignments of 
the form "a=b", one on each line. I am finding that the variable assignments 
are being lost.

Here is a simplified version of my script which illustrates the problem:

echo "myvar=my value" | while read opt; do 
if echo "$opt" | grep -q '='; then
var=`echo "$opt" | /bin/sed "s/=.*//"`
val=`echo "$opt" | /bin/sed "s/[^=]*=//"`
eval $var=\'$val\'
echo "(1)" $var=\'$val\'
echo "(2) myvar=$myvar"
fi
done
echo "(3) myvar=$myvar"

Which yields this:

(1) myvar='my value'
(2) myvar=my value
(3) myvar=

I am using Busybox v1.18.4

Any idea what is going on?
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Chuck Meade
On 05/25/2011 10:24 AM, Nigel Hathaway wrote:
> I'm trying to import a set of variables from a file containing assignments of 
> the form "a=b", one on each line. I am finding that the variable assignments 
> are being lost.
> 
> Here is a simplified version of my script which illustrates the problem:
> 
> echo "myvar=my value" | while read opt; do 
> if echo "$opt" | grep -q '='; then
> var=`echo "$opt" | /bin/sed "s/=.*//"`
> val=`echo "$opt" | /bin/sed "s/[^=]*=//"`
> eval $var=\'$val\'
> echo "(1)" $var=\'$val\'
> echo "(2) myvar=$myvar"
> fi
> done
> echo "(3) myvar=$myvar"
> 
> Which yields this:
> 
> (1) myvar='my value'
> (2) myvar=my value
> (3) myvar=
> 
> I am using Busybox v1.18.4
> 
> Any idea what is going on?

Hi Nigel,

You will get the same results if you run that logic through bash.
The problem is that your eval logic only has effect until the loop
(everything after the pipe '|') ends.

Run it in bash and you will see the same thing.

Chuck
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Yann E. MORIN
Nigel, All,

On Wednesday 25 May 2011 162459 Nigel Hathaway wrote:
> I'm trying to import a set of variables from a file containing assignments
> of the form "a=b", one on each line. I am finding that the variable
> assignments are being lost.
> 
> Here is a simplified version of my script which illustrates the problem:
> 
> echo "myvar=my value" | while read opt; do 
> if echo "$opt" | grep -q '='; then
> var=`echo "$opt" | /bin/sed "s/=.*//"`
> val=`echo "$opt" | /bin/sed "s/[^=]*=//"`
> eval $var=\'$val\'
> echo "(1)" $var=\'$val\'
> echo "(2) myvar=$myvar"
> fi
> done
> echo "(3) myvar=$myvar"
> 
> Which yields this:
> 
> (1) myvar='my value'
> (2) myvar=my value
> (3) myvar=
> 
> I am using Busybox v1.18.4
> 
> Any idea what is going on?

That's expected. All that is to the right part of the pipe is running in a
sub-shell. So the evaluation is done in a sub-shell. So it is lost as soon
as this sub-shell ends.

Regards,
Yann E. MORIN.

PS. Nigel, sorry for the duplicate, previous mail sent form the wrong
address, so got refused by the ML.
YEM.

-- 
.-..--..
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +0/33 662376056 | Software  Designer | \ / CAMPAIGN |   ^|
| --==< O_o >==-- '.---:  X  AGAINST  |  /e\  There is no  |
| http://ymorin.is-a-geek.org/ | (*_*) | / \ HTML MAIL|  """  conspiracy.  |
'--'---'--''
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


RE: Ash eval wierdness

2011-05-25 Thread Nigel Hathaway
Do you know what the solution is?

I've tried the 'set' command, but this doesn't seem to behave according 
standard ash set (according to the 'set' manpage)

On 05/25/2011 10:24 AM, Nigel Hathaway wrote:
> I'm trying to import a set of variables from a file containing assignments of 
> the form "a=b", one on each line. I am finding that the variable assignments 
> are being lost.
> 
> Here is a simplified version of my script which illustrates the problem:
> 
> echo "myvar=my value" | while read opt; do 
> if echo "$opt" | grep -q '='; then
> var=`echo "$opt" | /bin/sed "s/=.*//"`
> val=`echo "$opt" | /bin/sed "s/[^=]*=//"`
> eval $var=\'$val\'
> echo "(1)" $var=\'$val\'
> echo "(2) myvar=$myvar"
> fi
> done
> echo "(3) myvar=$myvar"
> 
> Which yields this:
> 
> (1) myvar='my value'
> (2) myvar=my value
> (3) myvar=
> 
> I am using Busybox v1.18.4
> 
> Any idea what is going on?

Hi Nigel,

You will get the same results if you run that logic through bash.
The problem is that your eval logic only has effect until the loop
(everything after the pipe '|') ends.

Run it in bash and you will see the same thing.

Chuck
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Yann E. MORIN
Nigel, All,

On Wednesday 25 May 2011 165635 Nigel Hathaway wrote:

Please, don't top-post. Write below the text you are replying to, it's
easier to follow and understand. Also, please wrap long lines to below
80 chars length.

> Do you know what the solution is?

Why do you need to add 'eval' in front of lines?
Does your input file contain only affectations, or other stuff?
Are affectations in this file properly escaped?

It all depends. If you have only affectations, and they are properly escaped
and/or quoted, then just source the file (notice the leading dot):
  . "${my_file}"

If not, then pre-process the file, stick 'eval' where it is due, escape
and/or quote where needed, and source the resulting file.

Regards,
Yann E. MORIN.

-- 
.-..--..
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +0/33 662376056 | Software  Designer | \ / CAMPAIGN |   ^|
| --==< O_o >==-- '.---:  X  AGAINST  |  /e\  There is no  |
| http://ymorin.is-a-geek.org/ | (*_*) | / \ HTML MAIL|  """  conspiracy.  |
'--'---'--''
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Harald Becker
 Hallo Chuck!

>> I'm trying to import a set of variables from a file containing assignments 
>> of the form "a=b", one on each line. I am finding that the variable 
>> assignments are being lost.
>>
>> Here is a simplified version of my script which illustrates the problem:
>>
>> echo "myvar=my value" | while read opt; do 
>> if echo "$opt" | grep -q '='; then
>> var=`echo "$opt" | /bin/sed "s/=.*//"`
>> val=`echo "$opt" | /bin/sed "s/[^=]*=//"`
>> eval $var=\'$val\'
>> echo "(1)" $var=\'$val\'
>> echo "(2) myvar=$myvar"
>> fi
>> done
>> echo "(3) myvar=$myvar"
>>
>> Which yields this:
>>
>> (1) myvar='my value'
>> (2) myvar=my value
>> (3) myvar=
>>
>> I am using Busybox v1.18.4
>>
>> Any idea what is going on?
> You will get the same results if you run that logic through bash.
> The problem is that your eval logic only has effect until the loop
> (everything after the pipe '|') ends.

In principle you are right, but it depends on the version of bash. There
exist two strategies which lead to different results in those cases.
Some shells run the last process in a pipe in the current shell others
the first process. If the shell runs the first process of a pipe, all
variable changes done by remaining processes of the pipe are lost. If
the shell runs the last process of a pipe, variable changes in the last
process are kept and others are lost.

In my eyes that last case is the better choice ... but ash uses the
other approach :-(

Hints:

If the variables are in usual shell syntax, why don't you source the
file direct to grab the variable values? That way you can use all types
of shell syntax for variable value definition, including substitutions,
arithmetical expressions etc.

[ -f YOUR_VAR_FILE ] && source YOUR_VAR_FILE

... or you can do ...

while read opt; do
   # process your opt value here
done http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Christopher Barry
On Wed, 2011-05-25 at 14:24 +, Nigel Hathaway wrote:
> I'm trying to import a set of variables from a file containing assignments of 
> the form "a=b", one on each line. I am finding that the variable assignments 
> are being lost.
> 
> Here is a simplified version of my script which illustrates the problem:
> 
> echo "myvar=my value" | while read opt; do 
> if echo "$opt" | grep -q '='; then
> var=`echo "$opt" | /bin/sed "s/=.*//"`
> val=`echo "$opt" | /bin/sed "s/[^=]*=//"`
> eval $var=\'$val\'
> echo "(1)" $var=\'$val\'
> echo "(2) myvar=$myvar"
> fi
> done
> echo "(3) myvar=$myvar"
> 
> Which yields this:
> 
> (1) myvar='my value'
> (2) myvar=my value
> (3) myvar=
> 
> I am using Busybox v1.18.4
> 
> Any idea what is going on?
> ___
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox

would this solve your problem?

grep '^[^[:blank:]]=.*$' file_with_vars_and_other_stuff >/tmp/varfile
. /tmp/varfile


-C


___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


RE: Ash eval wierdness

2011-05-25 Thread Nigel Hathaway
>
> Hallo Chuck!
>
>>> I'm trying to import a set of variables from a file containing >assignments 
>>> of the form "a=b", one on each line. I am finding that the >variable 
>>> assignments are being lost.
>>>
>>> Here is a simplified version of my script which illustrates the problem:
>>>
>>> echo "myvar=my value" | while read opt; do 
>>> if echo "$opt" | grep -q '='; then
>>> var=`echo "$opt" | /bin/sed "s/=.*//"`
>>> val=`echo "$opt" | /bin/sed "s/[^=]*=//"`
>>> eval $var=\'$val\'
>>> echo "(1)" $var=\'$val\'
>>> echo "(2) myvar=$myvar"
>>> fi
>>> done
>>> echo "(3) myvar=$myvar"
>>>
>>> Which yields this:
>>>
>>> (1) myvar='my value'
>>> (2) myvar=my value
>>> (3) myvar=
>>>
>>> I am using Busybox v1.18.4
>>>
>>> Any idea what is going on?
>> You will get the same results if you run that logic through bash.
>> The problem is that your eval logic only has effect until the loop
>> (everything after the pipe '|') ends.
>
>In principle you are right, but it depends on the version of bash. There
>exist two strategies which lead to different results in those cases.
>Some shells run the last process in a pipe in the current shell others
>the first process. If the shell runs the first process of a pipe, all
>variable changes done by remaining processes of the pipe are lost. If
>the shell runs the last process of a pipe, variable changes in the last
>process are kept and others are lost.
>
>In my eyes that last case is the better choice ... but ash uses the
>other approach :-(
>
>Hints:
>
>If the variables are in usual shell syntax, why don't you source the
>file direct to grab the variable values? That way you can use all types
>of shell syntax for variable value definition, including substitutions,
>arithmetical expressions etc.
>
>[ -f YOUR_VAR_FILE ] && source YOUR_VAR_FILE
>
>... or you can do ...
>
>while read opt; do
>   # process your opt value here
>done 
>... or another solution I'm using instead ...
>
>eval $( sed -e SCRIPT_TO_MODIFY_VAR_FILE YOUR_VAR_FILE )
>

Thanks for this very simple piece of script gymnastics. This last one is 
just the solution I was looking for.

>--
>Harald

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Bob Dunlop

Most of the responses didn't spot the spaces in your parameters which
I expect is causing most of your problems.

How's this for a solution if you have the parameters in "file".

  eval $(sed -n -e 's/=\(.*\)/="\1"/p' < file)

The sed does the equivalent of your grep and individual echo/seds
echoing the parameters with quotes to be evaluated in the parent shell.


Of course " in the file will cause problems and a whole host of other
things could lead to nasty security holes, but then you know that.
-- 
Bob Dunlop
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Denys Vlasenko
On Wed, May 25, 2011 at 4:24 PM, Nigel Hathaway
 wrote:
> I'm trying to import a set of variables from a file containing assignments of 
> the form "a=b", one on each line. I am finding that the variable assignments 
> are being lost.
>
> Here is a simplified version of my script which illustrates the problem:
>
> echo "myvar=my value" | while read opt; do
>    if echo "$opt" | grep -q '='; then
>        var=`echo "$opt" | /bin/sed "s/=.*//"`
>        val=`echo "$opt" | /bin/sed "s/[^=]*=//"`

This is inefficient (to run grep and two seds), and unsafe.

Efficiency:
if opt="a=b=c", then

var="${opt%%=*}"   #gives you "a" and
val="${opt#*=}" #gives you "b=c"

Correctness:
if test x"$var" = x"$opt"; then < there is no '='>

squote="'"
if test x"${val#*$squote}" != x"$val"; then < val contains single
quote, using '$val' won't be safe>


> echo "myvar=my value" | while read opt; do
...
>        eval $var=\'$val\'
>        echo "(1)" $var=\'$val\'
>        echo "(2) myvar=$myvar"
>    fi
> done

"while ... done http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Paul Smith
On Wed, 2011-05-25 at 17:20 +0200, Harald Becker wrote:
> In principle you are right, but it depends on the version of bash.
> There exist two strategies which lead to different results in those
> cases. Some shells run the last process in a pipe in the current shell
> others the first process. If the shell runs the first process of a
> pipe, all variable changes done by remaining processes of the pipe are
> lost. If the shell runs the last process of a pipe, variable changes
> in the last process are kept and others are lost.

Is it really the case that there are shells that run the first command
in a pipeline in the current shell?  I've never heard of this.

There are some shells that run the last command in a pipeline in the
current shell: ksh does this for example.  The last time I checked bash
does NOT do this, although maybe this was added in the latest versions?
I don't remember if zsh does this or not.

All other shells I'm aware of fork _all_ the commands in the pipeline.

Either method is acceptable from the standpoint of POSIX, so no shell
script that uses #!/bin/sh should ever depend on the "ksh behavior".

I agree it's a shame because it is so often useful to preserve variables
in the final command.  But, that's the way it is and it seems unlikely
to change.

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Rich Felker
On Wed, May 25, 2011 at 04:33:56PM +0200, Yann E. MORIN wrote:
> > echo "myvar=my value" | while read opt; do 
[...]
> 
> That's expected. All that is to the right part of the pipe is running in a
> sub-shell. So the evaluation is done in a sub-shell. So it is lost as soon
> as this sub-shell ends.

The canonical solution is:

while read opt; do ... ; done << EOF
myvar=my value
EOF

Rich
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: Ash eval wierdness

2011-05-25 Thread Harald Becker
 Hallo Bob!

>   eval $(sed -n -e 's/=\(.*\)/="\1"/p' < file)

Why do you redirect the input file here?

eval $( sed -n -e 's/=\(.*\)/="\1"/p' file )

... shall do the job.

In addition it is possible to strip of spaces around = (if required):

eval $( sed -n -e 's/ *= *\(.*\)/="\1"/p' file )

With some more tricky sed scripts you can even suppress comments in the
file, select only specific variables for usage and more, e.g.

eval $( sed -n \
-e '/^$/d' \
-e '/^#/d' \
-e 's/^\([a-z_]+\) *= *\(.*\)/\1="\2"/' \
-e '/^abc=/p' \
-e '/^xyz=/p' \
file )

... just to give some examples.

--
Harald
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox