[nuby] it seems that (?!...) doesn't work for me

L

Lionel Thiry

I'd like to make some kind of substitution like in a shell: "${var}".
For that purpose, I use this pattern: /\$\{(.*?)\}/.

But I also want to be able to escape those special caracters $, { and }.
Examples:
"${var\\}weird}" # which is a variable with "var{weird" as name
"\\${var}" # which is the simple string "${var}" with no substitution

Then I wrote that pattern:
/(?!\\)\$\{(.*?)(?!\\)\}/

But, well, it doesn't work at all.

After some tests:
puts "ok" if "\\{".match(/\\\{/) # display "ok"
puts "not ok" if "\\{".match(/(?!\\)\{/) # display "not ok"

It seems that (?!\\) doesn't fullfill its role of "match if re in (?!re)
doesn't match". What's wrong with my code? Please help!

My ruby version is the "One-Click Installer - Windows" v1.8.1-13.

Lio
 
T

ts

L> It seems that (?!\\) doesn't fullfill its role of "match if re in (?!re)
L> doesn't match". What's wrong with my code?

(?!re) is a zero-width negative look-*ahead* assertion. Apparently you
want a zero-width negative look-*behind* assertion which is (?<!re) and
implemented only in Oniguruma


svg% cat b.rb
#!./ruby
["${var\\}weird}", "\\${var}", "${var}"].each do |m|
p "#{m} -- #$1" if m.match(/(?<!\\)\$\{(.*?)(?<!\\)\}/)
end
svg%

svg% ruby b.rb
"${var\\}weird} -- var\\}weird"
"${var} -- var"
svg%



Guy Decoux
 
L

Lionel Thiry

ts a écrit :
L> It seems that (?!\\) doesn't fullfill its role of "match if re in (?!re)
L> doesn't match". What's wrong with my code?

(?!re) is a zero-width negative look-*ahead* assertion. Apparently you
want a zero-width negative look-*behind* assertion which is (?<!re) and
implemented only in Oniguruma
That's right, that's probably what I want... but how do I use oniguruma?



Lionel Thiry
 
T

ts

L> That's right, that's probably what I want... but how do I use oniguruma?

Oniguruma is in 1.9, but be carefull and don't forget that the regexp
engine is stupid

svg% ruby -e 'puts "not" unless "\\\\${var}".match(/(?<!\\)\$\{(.*?)(?<!\\)\}/)'
not
svg%



Guy Decoux
 
F

Florian G. Pflug

Lionel said:
I'd like to make some kind of substitution like in a shell: "${var}".
For that purpose, I use this pattern: /\$\{(.*?)\}/.

But I also want to be able to escape those special caracters $, { and
}. Examples:
"${var\\}weird}" # which is a variable with "var{weird" as name
"\\${var}" # which is the simple string "${var}" with no substitution

Use: /(^|[^\\]|(\\\\)+)\$\{(([^\}\\]|(\\.))*)\}/

I testes this with:
puts
(STDIN.readlines.join("\n").gsub(/(^|[^\\]|(\\\\)+)\$\{(([^\}\\]|(\\.))*)\}/m)
{|m| "#{$1}--#{$3.gsub(/\\(.)/, "\\1")}--"})
And it seems to work (replaces ${var} with --var--, but only if not
escaped).

The first part (/(^|[^\\]|(\\\\)+)/) basically means "either
start-of-string, non-backslash, or an even amount of backslash".
The part (/\{(([^\}\\]|(\\.))*)\}/) means "start with {, and than allow
any number of groups that consist of either a sequence of non-} and
non-\, or
of an escaped character (/\\./).

greetings, Florian Pflug
 
L

Lionel Thiry

Florian G. Pflug a écrit :
Lionel said:
I'd like to make some kind of substitution like in a shell: "${var}".
For that purpose, I use this pattern: /\$\{(.*?)\}/.

But I also want to be able to escape those special caracters $, { and
}. Examples:
"${var\\}weird}" # which is a variable with "var{weird" as name
"\\${var}" # which is the simple string "${var}" with no substitution


Use: /(^|[^\\]|(\\\\)+)\$\{(([^\}\\]|(\\.))*)\}/

I testes this with:
puts
(STDIN.readlines.join("\n").gsub(/(^|[^\\]|(\\\\)+)\$\{(([^\}\\]|(\\.))*)\}/m)
{|m| "#{$1}--#{$3.gsub(/\\(.)/, "\\1")}--"})
And it seems to work (replaces ${var} with --var--, but only if not
escaped).

The first part (/(^|[^\\]|(\\\\)+)/) basically means "either
start-of-string, non-backslash, or an even amount of backslash".
The part (/\{(([^\}\\]|(\\.))*)\}/) means "start with {, and than allow
any number of groups that consist of either a sequence of non-} and
non-\, or
of an escaped character (/\\./).

greetings, Florian Pflug

Thanks a lot for the help, but the pattern you gave is not perfect:

re = /(^|[^\\]|(\\\\)+)\$\{(([^\}\\]|(\\.))*)\}/
'pre${var}'.match # => prematch is "pr"

Lionel Thiry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,149
Latest member
Vinay Kumar Nevatia0
Top