gsub help

H

hurcan solter

Hi there;
this is more of a regexp question but I'de be happy if you help me
since i am doing it in ruby.
i want to beautify some line by inserting or removing some space
around the operators like = or ==
so i came up with an expression like;

line.gsub!(/\s*([=]+)\s*/ ,' \1 ')

But it applies every = on the line ofc, but I want to exclude
expressions between quotation marks ("sth=sth") or regexp (/sth=sth/).
I've tried negated character classes and such to no avail.How can I do
this?
Any help would be greatly appreciated...
Hurcan
 
D

Dan Zwell

hurcan said:
Hi there;
this is more of a regexp question but I'de be happy if you help me
since i am doing it in ruby.
i want to beautify some line by inserting or removing some space
around the operators like = or ==
so i came up with an expression like;

line.gsub!(/\s*([=]+)\s*/ ,' \1 ')

But it applies every = on the line ofc, but I want to exclude
expressions between quotation marks ("sth=sth") or regexp (/sth=sth/).
I've tried negated character classes and such to no avail.How can I do
this?
Any help would be greatly appreciated...
Hurcan

Hurcan,
That's a very hard problem. If you think creatively, you can probably
come up with a decent algorithm, and then a handful of examples that
break it. For each "=" or "==", you need to decide whether it is between
a pair of unescaped slashes, quotes, or other form of quoting (like %Q||
or %x{}). I doubt there is any way to do this with a regexp. You need to
write some code that makes decisions about whether any of the following
symbols has semantic meaning:
|\{}@^#() and any other that can be used in the % quoting construct

Once you determine which ones have meaning (and which are escaped, or
insignificant in their current context), you can decide whether some "="
should be re-spaced, based on its position relative to these characters.
The more I think about it, the more I think you can't do this without
writing a ruby parser.

puts ("this problem is nontrivial" == true)
puts %q("this problem is nontrivial" == true)
puts %q("this problem is nontrivial", says a

string == true)

Good luck,
Dan
 
L

Logan Capaldo

Hi there;
this is more of a regexp question but I'de be happy if you help me
since i am doing it in ruby.
i want to beautify some line by inserting or removing some space
around the operators like = or ==
so i came up with an expression like;

line.gsub!(/\s*([=]+)\s*/ ,' \1 ')

But it applies every = on the line ofc, but I want to exclude
expressions between quotation marks ("sth=sth") or regexp (/sth=sth/).
I've tried negated character classes and such to no avail.How can I do
this?
This is not a job for regexps. This is a job for a ruby parser.
 
W

William James

Hi there;
this is more of a regexp question but I'de be happy if you help me
since i am doing it in ruby.
i want to beautify some line by inserting or removing some space
around the operators like = or ==
so i came up with an expression like;

line.gsub!(/\s*([=]+)\s*/ ,' \1 ')

But it applies every = on the line ofc, but I want to exclude
expressions between quotation marks ("sth=sth") or regexp (/sth=sth/).
I've tried negated character classes and such to no avail.How can I do
this?
Any help would be greatly appreciated...
Hurcan

If " and / are the only wrappers you have to worry
about, this may work.

DATA.each{|line|
line.chomp!

array = line.scan(
%r{
\G
(?:
[^"/]+
|
"
(?> \\. | [^"] ) *
"
|
/
(?> \\. | [^/] ) *
/
)
}xm
).map{|s|
if s =~ %r{^[^"/]}
s.gsub!( /\s*(=+)\s*/, ' \1 ' )
end
s
}
puts array.join

}

__END__
/x==9/ { print "x==9 and AWK is everywhere!"; x=9 }
/\/x==9/ { print "x==\"9"; x==9 }
 
P

Peña, Botp

From: hurcan solter [mailto:[email protected]]=20
# line.gsub!(/\s*([=3D]+)\s*/ ,' \1 ')
#=20
# But it applies every =3D on the line ofc, but I want to exclude
# expressions between quotation marks ("sth=3Dsth") or regexp =
(/sth=3Dsth/).

after reviewing WJames post (thanks james), i think you are not far to =
the solution. You just need to include the exceptions first, then gsub =
further to that. gsub accepts a block, so flexibility is unlimited, eg,
=3D> "/x=3D=3D9/ { print \"x=3D=3D9 and AWK is everywhere!\"; x=3D9 }"

let's create our main regex sub and test if we can get back to the =
original str,
p str.gsub(/\S*\s*([=3D]+)\s*\S*/){|s| s }
"/x=3D=3D9/ { print \"x=3D=3D9 and AWK is everywhere!\"; x=3D9 }"
=3D> nil

ok. now let's view our captures. let's put some markers/tags.
p str.gsub(/\S*\s*([=3D]+)\s*\S*/){|s| "<<"+s+">>" }
"<</x=3D=3D9/>> { print <<\"x=3D=3D9>> and AWK is everywhere!\"; =
<<x=3D9>> }"
=3D> nil

ah, i think we're capturing right for this case of str

now let's test the inner substitution. note the gsub inside the block. =
the expression gets simpler since we've already filtered thru the =
first/main regexp.
p str.gsub(/\S*\s*([=3D]+)\s*\S*/){|s| s.gsub(/(=3D+)/,' \1 ') } =20
"/x =3D=3D 9/ { print \"x =3D=3D 9 and AWK is everywhere!\"; x =3D 9 }"
=3D> nil

ok.
now, let us combine that one w the first one (the noop), using an inline =
if (i'm assumming you want a one-liner) filtering thru the exception you =
want, ie, no ["\/]
p str.gsub(/\S*\s*([=3D]+)\s*\S*/){|s| s=3D~/["\/]/ ? s : =
s.gsub(/(=3D+)/,' \1 ') }
"/x=3D=3D9/ { print \"x=3D=3D9 and AWK is everywhere!\"; x =3D 9 }"
=3D> nil

is that ok?

kind regards -botp
 
T

Thibaut Barrère

This is not a job for regexps. This is a job for a ruby parser.

Maybe parsing with http://www.zenspider.com/ZSS/Products/ParseTree/
then regenerating the source from the parsed output could be good.

(didn't try myself - this is just a rough idea, and you would have to
ensure nothing get missed by the parser!)

Thibaut
 
W

William James

From: hurcan solter [mailto:[email protected]]
# line.gsub!(/\s*([=]+)\s*/ ,' \1 ')
#
# But it applies every = on the line ofc, but I want to exclude
# expressions between quotation marks ("sth=sth") or regexp (/sth=sth/).

after reviewing WJames post (thanks james), i think you are not far to the solution. You just need to include the exceptions first, then gsub further to that. gsub accepts a block, so flexibility is unlimited, eg,

=> "/x==9/ { print \"x==9 and AWK is everywhere!\"; x=9 }"

let's create our main regex sub and test if we can get back to the original str,
p str.gsub(/\S*\s*([=]+)\s*\S*/){|s| s }

"/x==9/ { print \"x==9 and AWK is everywhere!\"; x=9 }"
=> nil

ok. now let's view our captures. let's put some markers/tags.
p str.gsub(/\S*\s*([=]+)\s*\S*/){|s| "<<"+s+">>" }

"<</x==9/>> { print <<\"x==9>> and AWK is everywhere!\"; <<x=9>> }"
=> nil

ah, i think we're capturing right for this case of str

now let's test the inner substitution. note the gsub inside the block. the expression gets simpler since we've already filtered thru the first/main regexp.
p str.gsub(/\S*\s*([=]+)\s*\S*/){|s| s.gsub(/(=+)/,' \1 ') }

"/x == 9/ { print \"x == 9 and AWK is everywhere!\"; x = 9 }"
=> nil

ok.
now, let us combine that one w the first one (the noop), using an inline if (i'm assumming you want a one-liner) filtering thru the exception you want, ie, no ["\/]
p str.gsub(/\S*\s*([=]+)\s*\S*/){|s| s=~/["\/]/ ? s : s.gsub(/(=+)/,' \1 ') }

"/x==9/ { print \"x==9 and AWK is everywhere!\"; x = 9 }"
=> nil
irb --prompt xmp
str='/x==9/ {print "so x=9 and AWK is everywhere!"; x=9 }'
==>"/x==9/ {print \"so x=9 and AWK is everywhere!\"; x=9 }"
str.gsub(/\S*\s*([=]+)\s*\S*/){|s|
s=~/["\/]/ ? s : s.gsub(/(=+)/,' \1 ') }
==>"/x==9/ {print \"so x = 9 and AWK is everywhere!\"; x = 9 }"
 

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
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top