# RegExp problem

**URL:** <https://www.ruby-forum.com/t/regexp-problem/153609>\
**Category:** Ruby\
**Created:** [November 19, 2008, 10:59am UTC](https://www.ruby-forum.com/t/regexp-problem/153609 "2008-11-19T10:59:36Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 10:59am UTC](https://www.ruby-forum.com/t/regexp-problem/153609/1 "2008-11-19T10:59:36Z")

</div>

Hy,

I would like to know how to extract a string delimited by too identical  
characters from an another string(of any length).

ex string=“rzerze@foo@rezrzgrtez” how to get (or match) the foo string

thanks for your help.

---

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 11:21am UTC](https://www.ruby-forum.com/t/regexp-problem/153609/2 "2008-11-19T11:21:23Z")

</div>

On Wed, Nov 19, 2008 at 10:55 AM, Jf Rejza [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hy,
> 
> I would like to know how to extract a string delimited by too identical  
> characters from an another string(of any length).
> 
> ex string=“rzerze@foo@rezrzgrtez” how to get (or match) the foo string

irb(main):016:0\> string=“rzerze@foo@rezrzgrtez”  
=\> “rzerze@foo@rezrzgrtez”  
irb(main):017:0\> (string.match /@(.\*?)@/)[1]  
=\> “foo”

I don’t quite understand the rest of your requirement. You mean  
delimited  
by a string, i.e. the @ above is a variable, or by two of any character  
present  
in a string? If it’s the former:

irb(main):018:0\> delimiter = “@”  
=\> “@”  
irb(main):019:0\> (string.match /#{delimiter}(.\*?)#{delimiter}/)[1]  
=\> “foo”

if it’s the latter, something like this might help:

irb(main):024:0\> re = Regexp.new("([#{delimiter}])(._)?\1")  
=\> /([@abcde])(._)?\1/  
irb(main):025:0\> string.match(re)[2]  
=\> “rze@foo@rezrzgrt”

It found the first ‘e’ as the delimiter, don’t know why it took the  
last ‘e’ as the other part of the delimiter, since I used a non-greedy  
group for the middle part. Any ideas, someone?

Hope this helps,

Jesus.

---

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 12:33pm UTC](https://www.ruby-forum.com/t/regexp-problem/153609/3 "2008-11-19T12:33:03Z")

</div>

On Wed, Nov 19, 2008 at 11:58 AM, Florian G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Actually the correct regexp is:
> 
> delimiter = Regexp.escape(delimiter)  
> /#{delimiter}[^#{delimiter}]\*#{delimiter}/
> 
> Read: The delimiter - an unspecified number of non-delimiter-characters -  
> the delimiter.
> 
> Otherwise, you too heavily rely on the behaviour of the library, when it  
> coms to the dot.

Hi Florian,

I don’t get what you mean by “too heavily rely”, I mean, you are  
always relying on the behaviour of the regexp library when it comes to  
everything, so if you know how the dot, the \* and the ? work in Ruby  
why is your regexp better than the proposed one?

Anyway I have realized I had a mistake in my regexp (I had the ?  
outside of the group, and not next to the \*). So fixing that:

irb(main):034:0\> string=“rzerze@foo@rezrzgrtez”  
=\> “rzerze@foo@rezrzgrtez”  
irb(main):035:0\> re = Regexp.new("([#{delimiter}])(._?)\1")  
=\> /([abcde])(._?)\1/  
irb(main):036:0\> string.match(re)[2]  
=\> “rz”

Now works as I intended. With your version:

irb(main):037:0\> re = /([#{delimiter}])([^#{delimiter}]_)\1/  
=\> /([abcde])([^abcde]_)\1/  
irb(main):038:0\> string.match(re)[2]  
=\> “rz”

works too. So I would like to know why would be one preferred over the  
other.

Jesus.

---

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 1:05pm UTC](https://www.ruby-forum.com/t/regexp-problem/153609/4 "2008-11-19T13:05:26Z")

</div>

> outside of the group, and not next to the _). So fixing that:  
> irb(main):037:0\> re = /([#{delimiter}])([^#{delimiter}]_)\1/  
> =\> /([abcde])([^abcde]\*)\1/  
> irb(main):038:0\> string.match(re)[2]  
> =\> “rz”
> 
> works too. So I would like to know why would be one preferred over  
> the other.
> 
> Jesus.

Hi Jesus,

Because you could get problems when you have things like this:

“foo@fooo@bar@batz@foo”

you rely on the the behaviour of the dot. Meaning: yours matches

fooo@bar@batz

Thus, it ignores all inner delimiters.  
In any case, mine matches:

[[“fooo”],[“batz”]] #String#scan output

Depending on how the dot is treated (greediness etc.), yours  
could also have other interpretations (like mine) while mine is  
clearer in  
that respect.

In a simple case with only 2 delimiters, it doesn’t matter.

Actually, mine wasn’t correct either, i also forgot the brackets…

/#{delimiter}([^#{delimiter}])\*#{delimiter}/

For more readibility, here is the version with delimiter = @:

/@([^@]\*)@/

Regards,  
Florian G.

---

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 12:02pm UTC](https://www.ruby-forum.com/t/regexp-problem/153609/5 "2008-11-19T12:02:32Z")

</div>

Actually the correct regexp is:

delimiter = Regexp.escape(delimiter)  
/#{delimiter}[^#{delimiter}]\*#{delimiter}/

Read: The delimiter - an unspecified number of non-delimiter-  
characters - the delimiter.

Otherwise, you too heavily rely on the behaviour of the library, when  
it coms to the dot.

Regards,  
Florian G.

---

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 2:23pm UTC](https://www.ruby-forum.com/t/regexp-problem/153609/6 "2008-11-19T14:23:27Z")

</div>

On Wed, Nov 19, 2008 at 1:01 PM, Florian G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Because you could get problems when you have things like this:
> 
> “foo@fooo@bar@batz@foo”
> 
> you rely on the the behaviour of the dot. Meaning: yours matches
> 
> fooo@bar@batz
> 
> Thus, it ignores all inner delimiters.

Well, with the correction, it doesn’t anymore:

irb(main):071:0\>  
“foo@fooo@bar@batz@foo”.match(/([#{delimiter}])(.\*?)\1/)[2]  
=\> “fooo”

> In any case, mine matches:
> 
> [[“fooo”],[“batz”]] #String#scan output

irb(main):072:0\> “foo@fooo@bar@batz@foo”.scan(/([#{delimiter}])(.\*?)\1/)  
=\> [[“@”, “fooo”], [“@”, “batz”]]

> Depending on how the dot is treated (greediness etc.), yours  
> could also have other interpretations (like mine) while mine is clearer in  
> that respect.

Well, obviously this only works as expected if you use the non-greedy  
version.  
But I understand what you mean about being clearer, more explicit.

> In a simple case with only 2 delimiters, it doesn’t matter.

With more delimiters present in the string, mine works too.

Thanks,

Jesus.

---

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 4:23pm UTC](https://www.ruby-forum.com/t/regexp-problem/153609/7 "2008-11-19T16:23:53Z")

</div>

Now that we are on the topic of Regular Expressions I have a question  
about the ruby implementation. Like I posted earlier I needed to parse  
something that looks like this:

- activity

- area

- activities\_in\_area

etc…

Last time I did complicated regexps seems to have been C# or possibly  
java. So I tried to match the whole thing with  
/(- (\w\*)\s\*?\n([\t]++ (\w+)\s\*(:\s\*(\w\*))?\s\*?\n)+\s\*)+/  
and then I was gonna extract the captured data but it isn’t available.  
All nested groups have only captured their latest match. Is there no  
regexp lib for ruby that can handle nested groups and save the  
captures? I solved it with nested scans instead and I have to admin  
that it is more readable, so I’m not sure what, exactly, I want with  
this message, except ask about the design choices involved. Why don’t  
we want proper captures?

```
table_name = /\- (\w*)\s*?\n/
field_name = /(\s+\+ (\w+)\s*(\:\s*(\w*))?\n)/
doc.scan /#{table_name}(#{field_name}+)/ do |tablename, fields|
  fields.scan field_name do |junk, fieldname, junk2, type|
    # here I can do what I want
  end
end

```

And on the topic of pattern matching, can you recommend any good  
library for parser generation in ruby? I want to write a grammar and  
get an AST.

einarmagnus

---

<div class="post-metadata">

**Author:** ![manchoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/91b2a8/32.png) [@manchoman](https://www.ruby-forum.com/u/manchoman)\
**Post date:** [November 19, 2008, 3:41pm UTC](https://www.ruby-forum.com/t/regexp-problem/153609/8 "2008-11-19T15:41:33Z")

</div>

On Wed, 19 Nov 2008 04:55:58 -0500, Jf Rejza wrote:

> Hy,
> 
> I would like to know how to extract a string delimited by too identical  
> characters from an another string(of any length).
> 
> ex string=“rzerze@foo@rezrzgrtez” how to get (or match) the foo string
> 
> thanks for your help.

string.split(/@/)[1]

–Ken
