[nuby] shell-like substitution in a string

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

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.

···

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}"

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

Any idea of how I could manage that?

you can get bash's exact parameter expansion like this:

   jib:~ > cat a.rb
   require 'session'

   class Expander
     def self::new(*a, &b)
       @instance = super
     end
     def initialize
       @bash = Session::Bash::new
     end
     def expand expr, context = {}
       context.each do |k,v|
         o, e = @bash.execute "#{ k }=#{ v }"
         raise e unless e.empty?
       end
       stdout, stderr = @bash.execute "cat <<eos\n#{ expr }\neos"
       raise stderr unless stderr.empty?
       context.each{|k,v| @bash.execute "unset #{ k }"}
       stdout.chomp
     end
   end

   ex = Expander::new

   expr = "${tool} -o ${target} -L${libpath} -l${lib} ${source}"

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

   cmd = ex.expand expr, env
   p cmd

   jib:~ > ruby a.rb
   "gcc -o hello.exe -L/usr/lib -lsomelib hello.c"

-a

···

On Thu, 14 Oct 2004, Lionel Thiry wrote:
--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
When you do something, you should burn yourself completely, like a good
bonfire, leaving no trace of yourself. --Shunryu Suzuki

===============================================================================

Hello Lionel,

That was quite a quiz you asked us :wink:

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}
~ \\rvar

~ $\${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

interpolation.rb (1.37 KB)

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

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

···

On Thu, 14 Oct 2004, Lionel Thiry wrote:

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 :wink:

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}

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}

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