[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[nuby] shell-like substitution in a string

Lionel Thiry

10/13/2004 3:40:00 PM

Hi!

I'd like to make some kind of substitution like in a shell, i.e. having:
"${tool} -o ${target} -L${libpath} -l${lib} ${source}"

with an env like this:
env = {
"tool" => "gcc",
"target" => "hello.exe",
"libpath" => "/usr/lib",
"lib" => "somelib",
"source" => "hello.c"
}

it should give:
"gcc -o hello.exe -L/usr/lib -lsomelib hello.c"


It is easy until I want to manage caracter escapement like
"${var\\}weird}" which should give env["var}weird"], "\\${var}" which
should give the simple string "${var}" and "\\\\${var}" which should be
equivalent to "\\" + env["var"].

Any idea of how I could manage that?



Lionel Thiry


5 Answers

Eivind Eklund

10/13/2004 3:59:00 PM

0

On Thu, 14 Oct 2004 00:40:23 +0900, Lionel Thiry <lthiry@skynet.be> wrote:
> Hi!
>
> I'd like to make some kind of substitution like in a shell, i.e. having:
> "${tool} -o ${target} -L${libpath} -l${lib} ${source}"

What's the full context of this?

In Ruby, you can interpolate into strings using "the #{code} part will
be replaced with whatever 'code' returns", so "5*5 is #{5*5}" becomes
"5*5 is 25".

However, because I don't really know your context, I don't know if
this can solve your problem. If it can't, please give more contextual
details.

Eivind.


Ara.T.Howard

10/13/2004 4:40:00 PM

0

Kaspar Schiess

10/14/2004 11:50:00 AM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello Lionel,

That was quite a quiz you asked us ;)

I have a solution using only 'regular' regular expressions, the one in
1.8.1. Thus: this solution works without oniguruma.

I work around the lookbehind trouble by appending three spaces in front
of the string.

I am sure this solution is hideously complicated and can be improoved.
Anyone ?

Here's the output:
~ bluna ${var\}weird}
~ bluna weird substitute

~ sh ${tool} -o ${target} -L${libpath} -l${lib} ${source}
~ sh gcc -o test.exe -L/usr/lib -lopengl render.c

~ \${var}
~ \${var}

~ \\${var}
~ \\rvar

~ $\${var}
~ $\${var}

~ $\$${var}
~ $\$rvar

with an env of

~ env = {
'var\}weird' => 'weird substitute',
'var' => 'rvar',
'tool' => 'gcc',
'target' => 'test.exe',
'libpath' => '/usr/lib',
'lib' => 'opengl',
'source' => 'render.c'
~ }

Hope this hits your nerv,
kaspar
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail....

iD8DBQFBbmnPFifl4CA0ImQRAjF/AJ4oweuSNuxknxcslsv0f3S9GFiebACfXO7B
GYygYzZW0Co4z5S2na7y5Os=
=wcON
-----END PGP SIGNATURE-----
tests = []

tests << 'bluna ${var\\}weird}'
tests << 'sh ${tool} -o ${target} -L${libpath} -l${lib} ${source}'
tests << '\\${var}'
tests << '\\\\${var}'
tests << '$\${var}'
tests << '$\$${var}'


env = {
'var\}weird' => 'weird substitute',
'var' => 'rvar',
'tool' => 'gcc',
'target' => 'test.exe',
'libpath' => '/usr/lib',
'lib' => 'opengl',
'source' => 'render.c'
}

class ShellExpander
REString = /
^
(?:
\\ . |
[^\\$] |
\$ \\ . |
\$ [^\\{]
){3,}
\$ \{
(
(?: \\ . | [^\\}] )*
)
}
/x

def initialize env={}
@env = env
end

# call-seq:
# #expand( str ) => str
def expand str
for_each_shell_expansion_in str do |var|
@env[var]
end
end

def for_each_shell_expansion_in str
tomatch = str
replacements = []
offset = 0
while str.length > 0
tomatch = ' '*3 + tomatch
offset -= 3
md = REString.match tomatch
break unless md

replacement = yield( md[1] )
i, j = offset+md.begin(1), offset+md.end(1)

replacements << [i, j, replacement] if replacement

offset += md.pre_match.length + md[0].length
tomatch = md.post_match
end

offset = 0
replacements.each do |from, to, rep|
str[ (offset+from-2)...(offset+to+1) ] = rep

offset += rep.length - (to-from+3)
end

str
end
end

expander = ShellExpander.new env

tests.each do |str|
puts
puts str
puts expander.expand(str)
end


Lionel Thiry

10/14/2004 10:36:00 PM

0

Ara.T.Howard@noaa.gov a écrit :

> On Thu, 14 Oct 2004, Lionel Thiry wrote:
>
>> Hi!
>>
>> I'd like to make some kind of substitution like in a shell, i.e. having:
>> "${tool} -o ${target} -L${libpath} -l${lib} ${source}"
>>
>> with an env like this:
>> env = {
>> "tool" => "gcc",
>> "target" => "hello.exe",
>> "libpath" => "/usr/lib",
>> "lib" => "somelib",
>> "source" => "hello.c"
>> }
>>
>> it should give:
>> "gcc -o hello.exe -L/usr/lib -lsomelib hello.c"
>>
>>
>> It is easy until I want to manage caracter escapement like
>> "${var\\}weird}" which should give env["var}weird"], "\\${var}" which
>> should give the simple string "${var}" and "\\\\${var}" which should be
>> equivalent to "\\" + env["var"].
>
>
> i don't think you need to worry about that since 'var}weird' is not a valid
> shell identifier - at least i can't seem to create a var by that name in
> the
> shell...
Pertinent remark, noted.

>
>> Any idea of how I could manage that?
>
>
> you can get bash's exact parameter expansion like this:
>
> jib:~ > cat a.rb
> require 'session'
I'm working on win2k with on-click installer ruby v1.8.1-13 and
unfortunately, there is no session file that can be required.

Lionel Thiry


Lionel Thiry

10/14/2004 10:52:00 PM

0

Hello!

Thanks for the help, but I can already handle the recursive expansion of
the strings. My main problem is about the pattern itself, it gives me
headaches.

Some comments follow.

Kaspar Schiess a écrit :

> Hello Lionel,
>
> That was quite a quiz you asked us ;)
>
> I have a solution using only 'regular' regular expressions, the one in
> 1.8.1. Thus: this solution works without oniguruma.
>
> I work around the lookbehind trouble by appending three spaces in front
> of the string.
>
> I am sure this solution is hideously complicated and can be improoved.
> Anyone ?
>
> Here's the output:
> ~ bluna ${var\}weird}
> ~ bluna weird substitute
>
> ~ sh ${tool} -o ${target} -L${libpath} -l${lib} ${source}
> ~ sh gcc -o test.exe -L/usr/lib -lopengl render.c
>
> ~ \${var}
> ~ \${var}
I'd prefer '${var}' as a result, is it possible? Doesn't the (?>re)
expression fit for that purpose? Or should I make some substitution
after the match?

>
> ~ \\${var}
> ~ \\rvar
>
> ~ $\${var}
> ~ $\${var}
In fact, this case should generate an exception, as a non escaped $
should always be immediately followed by a {.

>
> ~ $\$${var}
> ~ $\$rvar
Idem.
But "\\$${var}" should give "$rvar", ideal for letting the shell to make
some postsubstitution with its usual env.

>
> with an env of
>
> ~ env = {
> 'var\}weird' => 'weird substitute',
> 'var' => 'rvar',
> 'tool' => 'gcc',
> 'target' => 'test.exe',
> 'libpath' => '/usr/lib',
> 'lib' => 'opengl',
> 'source' => 'render.c'
> ~ }
>
> Hope this hits your nerv,
> kaspar
I still have a lot of work, but thanks for the help.

Lionel Thiry