# Newbie: Strings and RegExp

**URL:** <https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888>\
**Category:** Ruby\
**Created:** [October 19, 2006, 6:00pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888 "2006-10-19T18:00:58Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 19, 2006, 6:00pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/1 "2006-10-19T18:00:58Z")

</div>

Hello,  
given an instance of String, str, how do you select/copy the section of  
the string between two given strings START\_STRING and END\_STRING?

I used something like:  
re = /#{STRING\_BEFORE}(regular\_expression)#{STRING\_AFTER}/  
str =~ re  
middle = $1  
where regular\_expression is supposed to be a regular expression  
selecting any character (digits, space, newline, character,  
anything…).

Is this the right method? And what should I use for regular\_expression?  
I tried (.|\n)\* but I get a “BUS error”. Any other way?

Or maybe is there a method which does what I need?

(Note: I am using Ruby 1.6.4 on Solaris)

Thank you

Diego

---

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 19, 2006, 6:17pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/2 "2006-10-19T18:17:01Z")

</div>

On 19.10.2006 17:56, Diego V. wrote:

> anything…).
> 
> Is this the right method? And what should I use for regular\_expression?  
> I tried (.|\n)\* but I get a “BUS error”. Any other way?

First, you do not need this alternation if you use /m (multiline mode).  
This regexp probably does an enourmous amount of backtracking because  
of this alternation. What’s in STRING\_BEFORE and STRING\_AFTER? If they  
contain regexp metacharacters you should probably do

/#{Regexp.escape STRING\_BEFORE}…

Depending on the length of your string, you might be better off with  
something like this:

array = str.split(/(#{Regexp.escape STRING\_BEFORE}|#{Regexp.escape  
STRING\_AFTER})/)

And then extract the middle portion from the resulting array.

> Or maybe is there a method which does what I need?
> 
> (Note: I am using Ruby 1.6.4 on Solaris)

That version is _ancient_. It might even have some bugs which are fixed  
in never versions. I strongly recommend to upgrade if possible.

Kind regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 19, 2006, 7:01pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/3 "2006-10-19T19:01:32Z")

</div>

Diego V. wrote:

> given an instance of String, str, how do you select/copy the section of  
> the string between two given strings START\_STRING and END\_STRING?

Here’s one way:  
STRING\_BEFORE = “hello”  
STRING\_AFTER = “goodbye”  
re = /#{STRING\_BEFORE}(.+?)#{STRING\_AFTER}/mo  
str = “I just wanted to say hello to you before I say goodbye for the  
final time.”  
str \<\< " Oh, hello and goodbye again."  
p str.scan( re ).flatten  
#=\> [" to you before I say ", " and "]

---

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 19, 2006, 7:33pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/4 "2006-10-19T19:33:36Z")

</div>

You should also be able to do this with split. Then you can use  
strings as well as regexes:

```
class String
  def match_between(head, tail)
    strings = []
    s = split(head, 2)[1]
    while (s)
      match, rest = s.split(tail,2)
      return strings unless rest
      strings << match
      s = rest.split(head, 2)[1]
    end
    strings
  end
end

```

So with the same string as before,

```
str = "I just wanted to say hello to you before I say goodbye for

```

the final time."  
str \<\< " Oh, hello and goodbye again."

you get:

```
p str.match_between(/hello/,/goodbye/)
# => [" to you before I say ", " and "]

```

and also

```
p str.match_between('a','e')
# => ["nt", "y h", "y goodby", "l tim", "nd goodby"]

```

I’m sure you could also tweek it to operate in a manner which doesn’t  
consume the rest of the string, i.e.: the ‘g’ flag.

---

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 19, 2006, 7:51pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/5 "2006-10-19T19:51:39Z")

</div>

> That version is _ancient_. It might even have some bugs which are fixed  
> in never versions. I strongly recommend to upgrade if possible.

Yes, I’d like to but it’s the Univeristy computer so I have to live  
with what there is. Sigh…

Diego

---

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 19, 2006, 7:51pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/6 "2006-10-19T19:51:39Z")

</div>

> Here’s one way:  
> STRING\_BEFORE = “hello”  
> STRING\_AFTER = “goodbye”  
> re = /#{STRING\_BEFORE}(.+?)#{STRING\_AFTER}/mo  
> str = “I just wanted to say hello to you before I say goodbye for the  
> final time.”  
> str \<\< " Oh, hello and goodbye again."  
> p str.scan( re ).flatten  
> #=\> [" to you before I say ", " and "]

Perfect, it works. Thanks a lot, and to Robert and Louis too, thanks.

So basically I gather the main problem was using the /mo. Right? That  
alone, with the simpler regular expression seems to do the job. (maybe  
before it was running out of memory? is that what bus error means?)

However here you are using /mo instead of /m. What does the extra o  
mean? And where can I read more about this topic? I’ve checked on the  
Pragmatic Programmer book (the one online) but I can’t find any info on  
that.

Thanks again.

Diego

---

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 19, 2006, 11:55pm UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/7 "2006-10-19T23:55:52Z")

</div>

Diego V. wrote:

> > That version is _ancient_. It might even have some bugs which are fixed  
> > in never versions. I strongly recommend to upgrade if possible.
> 
> Yes, I’d like to but it’s the Univeristy computer so I have to live  
> with what there is. Sigh…

🙂 I believe you can compile Ruby in a way and install it completely  
in your home directory. That of course works only if your quota is high  
enough. Maybe worth a try.

Good luck!

```
robert
```

---

<div class="post-metadata">

**Author:** ![diego\_v](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/eb8c5e/32.png) [@diego\_v](https://www.ruby-forum.com/u/diego_v)\
**Post date:** [October 20, 2006, 7:33am UTC](https://www.ruby-forum.com/t/newbie-strings-and-regexp/72888/8 "2006-10-20T07:33:03Z")

</div>

You absolutely can compile and install to home, just set the --prefix to  
something like  
–prefix=/usr/local/home/yours/ruby-1\_8/

Then make sure the bin directory is in your path before the system  
installed ruby that way env ruby picks up your new install.
