# Ruby Regexp vs Perl and C#

**URL:** <https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981>\
**Category:** Ruby\
**Created:** [October 13, 2006, 2:00am UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981 "2006-10-13T02:00:22Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![chrismalek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/6de8d8/32.png) [@chrismalek](https://www.ruby-forum.com/u/chrismalek)\
**Post date:** [October 13, 2006, 2:00am UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981/1 "2006-10-13T02:00:22Z")

</div>

I am having trouble with the Ruby regexp engine and don’t know if it is  
my lack of experience with Ruby, or if it just isn’t possible to do  
certain things with the Ruby engine. Basically I have the following  
code in perl and C#, simplified for the example:

Perl:  
$line = “banana”;  
while( $line =~ /(an)\*/g )  
{  
print $`. “\<\<” . $& . “\>\>” . $’ . “\n”;  
}

C#:  
using System;  
using System.Text.RegularExpressions;

public class MyClass  
{  
public static void Main()  
{  
string testString = “banana”;  
MatchCollection matches = Regex.Matches( testString, “(an)\*” );  
foreach( Match match in matches)  
{  
Console.WriteLine( testString.Substring( 0, match.Index) +  
“\<\<” + match.Value + “\>\>” + testString.Substring( match.Index +  
match.Length));  
}  
}  
}

Output from both:  
\<\<\>\>banana  
b\<\>a  
banan\<\<\>\>a  
banana\<\<\>\>

While the C# way of getting the answer is a bit more messy, it is still  
possible. I am wondering if/how to do this in Ruby. From what I have  
seen, all the Ruby options are a single match which doesn’t help me,  
especially with the given example where Ruby’s only match would be the  
one before the string thus being empty. Using the string#scan in ruby  
also doesn’t help as it gives a 2 dimensional array of the following:  
Ruby:  
irb(main):001:0\> line = “banana”  
=\> “banana”  
irb(main):002:0\> line.scan(/(an)\*/)  
=\> [[nil], [“an”], [nil], [nil]]

So while Ruby finds that there should be 4 matches, it returns them in a  
difficult to use format, with no index information, and matches only  
“an” rather than “anan” as I want.

So basically is there a way to do this in Ruby? Which can also be asked  
as, how do you do multiple matches in Ruby with full match information?

Thanks,  
Chris

---

<div class="post-metadata">

**Author:** ![chrismalek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/6de8d8/32.png) [@chrismalek](https://www.ruby-forum.com/u/chrismalek)\
**Post date:** [October 16, 2006, 7:29pm UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981/2 "2006-10-16T19:29:48Z")

</div>

Verno Miller wrote:

> It’s a bit tricky but still doable!
> 
> line = “banana”
> 
> If your goal is to match just (an)\* in “banana” use:
> 
> line.scan(/((an)\*)/) { |str|  
> #puts $1.inspect  
> puts $1 if $1 != “”  
> }

Thank you Verno, that is what I needed. By using the block syntax I am  
able to get the same output as Perl or C# and I can adapt that to my  
problem at hand. For anyone interested, to recreate the same output in  
Ruby as my Perl and C# example the following code works:

line=“banana”  
line.scan(/(an)\*/) {  
puts $` + “\<\<” + $& + “\>\>” + $’ + “\n”  
}

Thanks again, Chris

---

<div class="post-metadata">

**Author:** ![chrismalek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/6de8d8/32.png) [@chrismalek](https://www.ruby-forum.com/u/chrismalek)\
**Post date:** [October 15, 2006, 12:22pm UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981/3 "2006-10-15T12:22:17Z")

</div>

> Chris M. wrote:  
> …  
> … and [Ruby] matches only “an” rather than “anan” as I want.
> 
> So basically is there a way to do this in Ruby? Which can also be asked  
> as, how do you do multiple matches in Ruby with full match information?
> 
> Thanks,  
> Chris

It’s a bit tricky but still doable!

line = “banana”

If your goal is to match just (an)\* in “banana” use:

line.scan(/((an)\*)/) { |str|  
#puts $1.inspect  
puts $1 if $1 != “”  
}

To match surrounding characters as well use:

line.scan(/([^a]|a(?=[^n]|$)|(an)\*)/) { |str|  
puts $1.inspect unless $1.empty?  
}

Additional characters can be inserted this way:

line = “bananaxyzantuia”

str = “”

line.scan(/([^a]|a(?=[^n]|$)|(an)\*)/) {

match = $1

puts match if match =~ /^[^a]$/  
puts match if match =~ /^a$/  
puts match if match =~ /^(an)+$/

if match =~ /^[^a]$/ then str \<\< match  
elsif match =~ /^a$/ then str \<\< match  
elsif match =~ /^(an)+$/ then str \<\< “\<\<” \<\< match \<\< “\>\>”  
end

}

puts str #=\> b\<\>axyz\<\>tuia

Instead of if-elsif-end you can also use case-when-end of course (cf.  
[BigBold - Informasi Tentang Bisnis dan Marketing](http://www.bigbold.com/snippets/posts/show/1313) ).

Cheers,  
verno

---

<div class="post-metadata">

**Author:** ![chrismalek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/6de8d8/32.png) [@chrismalek](https://www.ruby-forum.com/u/chrismalek)\
**Post date:** [October 17, 2006, 7:41am UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981/4 "2006-10-17T07:41:18Z")

</div>

On 10/16/06, Chris M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> line=“banana”  
> line.scan(/(an)\*/) {  
> puts $` + “\<\<” + $& + “\>\>” + $’ + “\n”  
> }

Also, if you do a

require ‘English’

you can write that as

puts $PREMATCH + “\<\<” + $MATCH + “\>\>” + $POSTMATCH

(you don’t need the explicit \n if you’re using puts)

martin

---

<div class="post-metadata">

**Author:** ![chrismalek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/6de8d8/32.png) [@chrismalek](https://www.ruby-forum.com/u/chrismalek)\
**Post date:** [October 18, 2006, 10:39am UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981/5 "2006-10-18T10:39:43Z")

</div>

matt neuburg [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Chris M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > how do you do multiple matches in Ruby with full match information?
> 
> gsub

In fact you could effectively write it exactly as you did it in Perl:

“banana”.gsub(/(an)\*/) {  
puts $` + “\<\<” + $& + “\>\>” + $’  
}

m.

---

<div class="post-metadata">

**Author:** ![chrismalek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/6de8d8/32.png) [@chrismalek](https://www.ruby-forum.com/u/chrismalek)\
**Post date:** [October 18, 2006, 10:39am UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981/6 "2006-10-18T10:39:46Z")

</div>

On Oct 12, 2006, at 7:00 PM, Chris M. wrote:

> ```
> print $`. "<<" . $& . ">>" . $' . "\n";
> 
> ```
> 
> }

scan() can also take a block:

“banana”.scan { puts “#{$`}\<\<#{$&}\>\>#{$’}” }

James Edward G. II

---

<div class="post-metadata">

**Author:** ![chrismalek](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/6de8d8/32.png) [@chrismalek](https://www.ruby-forum.com/u/chrismalek)\
**Post date:** [October 18, 2006, 10:39am UTC](https://www.ruby-forum.com/t/ruby-regexp-vs-perl-and-c/71981/7 "2006-10-18T10:39:41Z")

</div>

Chris M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> how do you do multiple matches in Ruby with full match information?

gsub

m.
