Return number of matches

C

Christopher Causer

This seems like an easy question but I cannot find any documentation on
it anywhere on the web.

I want to write a script that will count the number of dollars in a
string, excluding escaped dollars (ie. "\$".) My first hack was to use
split and count the number of elements in the array, but I came unstuck
trying to exclude \$. Surely there's a nice simple elegant solution?

I'm very (as in this morning) new to Ruby so apologies if this is a
trivial question and I'm posting on the wrong forum.

Chris
 
J

Jano Svitok

This seems like an easy question but I cannot find any documentation on
it anywhere on the web.

I want to write a script that will count the number of dollars in a
string, excluding escaped dollars (ie. "\$".) My first hack was to use
split and count the number of elements in the array, but I came unstuck
trying to exclude \$. Surely there's a nice simple elegant solution?

Easy solution: count $ and subtract \$ ;-)

string.scan(/\$/).size - string.scan(/\\\$/).size

It's possible to do it in one regex, but it won't be nice and elegant
and I don't have the time now to try it...
 
C

Christopher Causer

Jano said:
It's possible to do it in one regex, but it won't be nice and elegant
and I don't have the time now to try it...

I was so psyched in doing it in one regexp that I completely missed the
absolute beauty that you posted. Thanks a lot for the help.
 
R

Robert Klemme

I was so psyched in doing it in one regexp that I completely missed the
absolute beauty that you posted. Thanks a lot for the help.

With 1.9 you can use negative lookbehind. If that's not available then
it becomes ugly (if it is possible at all). The simplest pre 1.9 single
pass solution that comes to mind is this

irb(main):012:0> c=0
=> 0
irb(main):013:0> "$\\$$".scan(/\$/) { c+=1 unless $`[-1] == ?\\ }
=> "$\\$$"
irb(main):014:0> c
=> 2

Kind regards

robert
 
W

William James

Easy solution: count $ and subtract \$ ;-)

string.scan(/\$/).size - string.scan(/\\\$/).size

It's possible to do it in one regex, but it won't be nice and elegant
and I don't have the time now to try it...

That fails when the backslash preceding a $
is itself escaped.
string = "$\\\\$"
==>"$\\\\$"
string.scan(/\$/).size - string.scan(/\\\$/).size
==>1

Try this:

p DATA.read.scan(/(\\.|[$])/).flatten.grep(/^.$/).size

__END__
$\\$\$$
 
C

Christopher Causer

William said:
That fails when the backslash preceding a $
is itself escaped.

string = "$\\\\$"
==>"$\\\\$"
string.scan(/\$/).size - string.scan(/\\\$/).size
==>1

Erm, not sure what you're trying to say. One is the answer I would have
wanted. Thanks anyway for the one liner though.

Just out of interest, why doesn't my first effort work?

string.scan(/[^\\]\$/).size

?
 
T

ThoML

string.scan(/[^\\]\$/).size

This fails on input like "$$$$", since the string will be split into "$
$", "$$". It will also not find the first $ in the string but this
could be amended by using (^|[^\\]).
 
J

Jano Svitok

Erm, not sure what you're trying to say. One is the answer I would have
wanted. Thanks anyway for the one liner though.

William's tring to say that you have three interesting items in your
string, and you haven't counted one:
a plain dollar $, escaped dollar \$ and escaped backslash \\. If
escaped backslash precedes unescaped dollar, \\$
in your definition of the problem (and in my solution) it is not counted.
 
W

William James

Erm, not sure what you're trying to say. One is the answer I would have
wanted. Thanks anyway for the one liner though.

You said that you wanted to count all dollar signs except the
escaped ones. So the correct answer is 2. The first backslash
escapes the second one, which escapes nothing.
 
C

Christopher Causer

William said:
You said that you wanted to count all dollar signs except the
escaped ones. So the correct answer is 2. The first backslash
escapes the second one, which escapes nothing.

Yes, thanks, I realize now. 1 was the answer I would have wanted because
it wasn't preceded by a space, but I could have made that much clearer
in my question.

Thanks a lot guys. You've been most helpful. Have loads more basic
questions like that. Is this the right forum for such questions?
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top