# String mangling

**URL:** <https://www.ruby-forum.com/t/string-mangling/50243>\
**Category:** Ruby\
**Created:** [December 14, 2005, 1:20pm UTC](https://www.ruby-forum.com/t/string-mangling/50243 "2005-12-14T13:20:48Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 14, 2005, 1:20pm UTC](https://www.ruby-forum.com/t/string-mangling/50243/1 "2005-12-14T13:20:48Z")

</div>

Imagine an input string  
aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee…

I have regexp for the parts a,b,c  
and e can be considered as else.

So how can I efficiently search/step through the string from left to  
right, while calling for each section the fitting handler, kind of

case section  
/aaaa/ …

/bbb/ …

/cccc/ …

else

end

Thanks for ideas!  
Martin

---

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 14, 2005, 1:35pm UTC](https://www.ruby-forum.com/t/string-mangling/50243/2 "2005-12-14T13:35:51Z")

</div>

On 12/14/05, Martin P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Imagine an input string  
> aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee…
> 
> I have regexp for the parts a,b,c  
> and e can be considered as else.
> 
> So how can I efficiently search/step through the string from left to  
> right, while calling for each section the fitting handler, kind of

irb(main):001:0\> s = ‘aaaaabbccccceeebbbbbbbbbbeaaabaacccceee’  
=\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceee”  
irb(main):002:0\> s.scan(/(a+)|(b+)|(c+)|([^abc]+)/)  
=\> [[“aaaaa”, nil, nil, nil], [nil, “bb”, nil, nil], [nil, nil,  
“ccccc”, nil], [nil, nil, nil, “eee”], [nil, “bbbbbbbbbb”, nil, nil],  
[nil, nil, nil, “e”], [“aaa”, nil, nil, nil], [nil, “b”, nil, nil],  
[“aa”, nil, nil, nil], [nil, nil, “cccc”, nil], [nil, nil, nil,  
“eee”]]  
irb(main):003:0\>

---

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 14, 2005, 2:14pm UTC](https://www.ruby-forum.com/t/string-mangling/50243/3 "2005-12-14T14:14:57Z")

</div>

Martin P. wrote:

> /aaaa/ …
> 
> /bbb/ …
> 
> /cccc/ …
> 
> else
> 
> end

You are pretty close:

> > s=‘aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee’  
> > =\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee”
> 
> > s.scan /a+|b+|c+/ do |m|  
> > ?\> case m
> 
> > ```
> > when /a+/
> > puts "A"
> > when /b+/
> > puts "B"
> > when /c+/
> > puts "C"
> > 
> > ```
> > 
> > end  
> > end  
> > A  
> > B  
> > C  
> > B  
> > A  
> > B  
> > A  
> > C  
> > =\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee”

Or, if you want to avoid a second match:

> > s.scan /(a+)|(b+)|(c+)/ do |m|  
> > ?\> case ( m.inject(0) {|i,e| break i if e; i + 1} )
> 
> > ```
> > when 0
> > puts "A"
> > when 1
> > puts "B"
> > when 2
> > puts "C"
> > 
> > ```
> > 
> > end  
> > end  
> > A  
> > B  
> > C  
> > B  
> > A  
> > B  
> > A  
> > C  
> > =\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee”
> 
> >

Kind regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 14, 2005, 2:14pm UTC](https://www.ruby-forum.com/t/string-mangling/50243/4 "2005-12-14T14:14:58Z")

</div>

Martin P. wrote:

> Imagine an input string  
> aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee…
> 
> I have regexp for the parts a,b,c  
> and e can be considered as else.
> 
> So how can I efficiently search/step through the string from left to  
> right, while calling for each section the fitting handler, kind of

You could use String#scan to find bits that find sections that match any  
of your requirements, then check to see which matched (your patterns  
could be more complicated, but still distinguishable from one another)

str = ‘aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee’

a\_rx = /a+/  
b\_rx = /b+/  
c\_rx = /c+/

str.scan(/(?:#{a\_rx}|#{b\_rx}|#{c\_rx})/) do | part |  
case part  
when a\_rx  
# …  
when b\_rx  
# …  
when c\_rx  
# …  
end  
end

---

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 14, 2005, 2:39pm UTC](https://www.ruby-forum.com/t/string-mangling/50243/5 "2005-12-14T14:39:01Z")

</div>

On Dec 14, 2005, at 6:32 AM, Simon S. wrote:

> irb(main):001:0\> s = ‘aaaaabbccccceeebbbbbbbbbbeaaabaacccceee’  
> =\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceee”  
> irb(main):002:0\> s.scan(/(a+)|(b+)|(c+)|([^abc]+)/)  
> =\> [[“aaaaa”, nil, nil, nil], [nil, “bb”, nil, nil], [nil, nil,  
> “ccccc”, nil], [nil, nil, nil, “eee”], [nil, “bbbbbbbbbb”, nil, nil],  
> [nil, nil, nil, “e”], [“aaa”, nil, nil, nil], [nil, “b”, nil, nil],  
> [“aa”, nil, nil, nil], [nil, nil, “cccc”, nil], [nil, nil, nil,  
> “eee”]]  
> irb(main):003:0\>

My similar thought:

> > str = ‘aaaaabbccccceeebbbbbbbbbbeaaabaacccceee’  
> > =\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceee”
> 
> > str.scan(/((\w)\2\*)/).map { |chunk| chunk.first }  
> > =\> [“aaaaa”, “bb”, “ccccc”, “eee”, “bbbbbbbbbb”, “e”, “aaa”, “b”,  
> > “aa”, “cccc”, “eee”]

James Edward G. II

---

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 14, 2005, 2:23pm UTC](https://www.ruby-forum.com/t/string-mangling/50243/6 "2005-12-14T14:23:59Z")

</div>

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

> > /aaaa/ …
> > 
> > /bbb/ …
> > 
> > /cccc/ …
> > 
> > else
> > 
> > end  
> > […]  
> > Or, if you want to avoid a second match:

of course I want 🙂

> A  
> B  
> C  
> B  
> A  
> B  
> A  
> C  
> =\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee”

…but this doesn’t allow a processing step in the “else” case?

Martin

---

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 14, 2005, 8:39pm UTC](https://www.ruby-forum.com/t/string-mangling/50243/7 "2005-12-14T20:39:37Z")

</div>

Martin P. wrote:

> Imagine an input string  
> aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee…
> 
> I have regexp for the parts a,b,c  
> and e can be considered as else.
> 
> So how can I efficiently search/step through the string from left to  
> right, while calling for each section the fitting handler, kind of
> 
> case section  
> /aaaa/ …
> 
> /bbb/ …
> 
> /cccc/ …
> 
> else
> 
> end

Aside from the oft-mentioned String#scan, you might look into  
using StringScanner (require ‘strscan’) from the stdlib. It is  
very good for more complex cases of scanning. Documentation is  
available, for example, at [RDoc Documentation](http://www.ruby-doc.org/stdlib).

> Thanks for ideas!  
> Martin

E

---

<div class="post-metadata">

**Author:** ![dhstudio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b487fb/32.png) [@dhstudio](https://www.ruby-forum.com/u/dhstudio)\
**Post date:** [December 15, 2005, 11:08am UTC](https://www.ruby-forum.com/t/string-mangling/50243/8 "2005-12-15T11:08:10Z")

</div>

Martin P. wrote:

> > > case section  
> > > Or, if you want to avoid a second match:
> > > 
> > > > ```
> > > > puts "C"
> > > > 
> > > > ```
> > 
> > =\> “aaaaabbccccceeebbbbbbbbbbeaaabaacccceeee”
> 
> …but this doesn’t allow a processing step in the “else” case?

You can have an else clause - but it will never be called. I guess you  
will process entries between matches. In that case scan won’t help - at  
least not as used in my example.

A simple option would be to use #split with a group around the whole  
regexp and then operate on the array of strings you get. Whether that’s  
feasible (volume?) in you case I cannot decide.

s.split(/((?:a+)|(?:b+)|(?:c+))/.each do |m|  
case section  
/aaaa/ …

/bbb/ …

/cccc/ …  
else  
end  
end

Kind regards

```
robert
```
