# String method to take subsections

**URL:** <https://www.ruby-forum.com/t/string-method-to-take-subsections/131756>\
**Category:** Ruby\
**Created:** [March 13, 2008, 1:18am UTC](https://www.ruby-forum.com/t/string-method-to-take-subsections/131756 "2008-03-13T01:18:48Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![glenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4bbf92/32.png) [@glenn](https://www.ruby-forum.com/u/glenn)\
**Post date:** [March 13, 2008, 1:18am UTC](https://www.ruby-forum.com/t/string-method-to-take-subsections/131756/1 "2008-03-13T01:18:48Z")

</div>

Hi,

I’m looking for a method for the String class that returns an array of  
strings based on two input strings.

For example, if you had the string ‘xxxxxa1byyyyya2bzzzzzzz’ I’d like it  
to return the smaller strings between ‘a’ and b’, but I don’t want the  
smaller strings to include either ‘a’ or ‘b’.

So, ‘xxxxxa1byyyyya2bzzzzzzz’.method\_x(‘a’, ‘b’) would return [“1”,  
“2”].

If you had the string ‘a1b2’ and tried ‘a1b2’.method\_x(‘a’, ‘c’) you’d  
get nil because ‘c’ is obviously not in the String that’s calling the  
method.

Likewise, if you tried ‘a1b2’.method\_x(‘b’, ‘a’) it would also return  
nil since there’s no string between ‘b’ and ‘a’ (so the order matters).

I looked but didn’t see anything quite like this.

Thanks!

Glenn

---

<div class="post-metadata">

**Author:** ![glenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4bbf92/32.png) [@glenn](https://www.ruby-forum.com/u/glenn)\
**Post date:** [March 13, 2008, 1:54am UTC](https://www.ruby-forum.com/t/string-method-to-take-subsections/131756/2 "2008-03-13T01:54:01Z")

</div>

Hi –

On Thu, 13 Mar 2008, Glenn wrote:

> Likewise, if you tried ‘a1b2’.method\_x(‘b’, ‘a’) it would also return nil since there’s no string between ‘b’ and ‘a’ (so the order matters).
> 
> I looked but didn’t see anything quite like this.

Have a look at String#scan.

‘xxxxxa1byyyyya2bzzzzzzz’.scan(/a(.\*?)b/)  
=\> [[“1”], [“2”]]

It may not be an exact fit for the calling syntax you want but you  
could wrap it in something else.

David

---

<div class="post-metadata">

**Author:** ![glenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4bbf92/32.png) [@glenn](https://www.ruby-forum.com/u/glenn)\
**Post date:** [March 13, 2008, 2:41am UTC](https://www.ruby-forum.com/t/string-method-to-take-subsections/131756/3 "2008-03-13T02:41:34Z")

</div>

Glenn wrote:

> Hi,
> 
> I’m looking for a method for the String class that returns an array of  
> strings based on two input strings.

Regular expressions are your friend here:

class String  
def containedby(startmark=‘a’,endmark=‘b’)  
self.scan(Regexp.new(startmark+’([^’+endmark+’]\*)’+endmark)).flatten  
end  
end

should do what you want. If you want to restrict it to just one  
character remove the \* in ‘]\*)’.

> If you had the string ‘a1b2’ and tried ‘a1b2’.method\_x(‘a’, ‘c’) you’d  
> get nil because ‘c’ is obviously not in the String that’s calling the  
> method.
> 
> Likewise, if you tried ‘a1b2’.method\_x(‘b’, ‘a’) it would also return  
> nil since there’s no string between ‘b’ and ‘a’ (so the order matters).

Actually returns [] in both these cases, but I’m sure you can deal with  
those.

# Test Listing and output below:

class String  
def containedby(startmark=‘a’,endmark=‘b’)  
self.scan(Regexp.new(Regexp.escape(startmark)+’([^’+Regexp.escape(endmark)+’]\*)’+Regexp.escape(endmark))).flatten  
end  
end

TEST=‘xxxxxa1byyyyya2bzzzzzzz’  
extracted=TEST.containedby(‘a’,‘b’)  
puts extracted.inspect  
extracted=TEST.containedby(‘a’,‘c’)  
puts extracted.inspect  
TEST2=‘b1a2’  
extracted=TEST2.containedby(‘a’,‘b’)  
puts extracted.inspect

=====================================

[“1”, “2”]  
[]  
[]

---

<div class="post-metadata">

**Author:** ![glenn](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/4bbf92/32.png) [@glenn](https://www.ruby-forum.com/u/glenn)\
**Post date:** [March 13, 2008, 2:01am UTC](https://www.ruby-forum.com/t/string-method-to-take-subsections/131756/4 "2008-03-13T02:01:38Z")

</div>

On Thu, Mar 13, 2008 at 1:18 AM, Glenn [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> So, ‘xxxxxa1byyyyya2bzzzzzzz’.method\_x(‘a’, ‘b’) would return [“1”, “2”].

You could use String#scan and wrap it in a method or extend the String  
class:

# So, ‘xxxxxa1byyyyya2bzzzzzzz’.method\_x(‘a’, ‘b’) would return [“1”,

“2”].

def method\_x(str, first, last)  
pattern = “#{first}(\d)#{last}”  
regexp = Regexp.new(pattern)  
return str.scan(regexp).flatten  
end

p method\_x(‘xxxxxa1byyyyya2bzzzzzzz’, ‘a’, ‘b’) #=\> [“1”, “2”].

# you could also extend the String class

class String  
def method\_x(first, last)  
pattern = “#{first}(\d)#{last}”  
regexp = Regexp.new(pattern)  
return self.scan(regexp).flatten  
end  
end

p ‘xxxxxa1byyyyya2bzzzzzzz’.method\_x(‘a’, ‘b’)
