# Regex replacement problem---replace every n-th

**URL:** <https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316>\
**Category:** Ruby\
**Created:** [March 1, 2006, 1:03pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316 "2006-03-01T13:03:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 1:03pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/1 "2006-03-01T13:03:45Z")

</div>

Hi all

I have the string '1 20 3 400 5 60 7 800 9 0 ’ and need to replace  
every n-th space in the string with another character. So if n=2 and  
the replacement character is ‘\n’, then the above would become

‘1 20\n3 400\n5 60\n7 800\n9 0\n’.

I’m sure it must be possible (easy, even) to do this with a regex  
substitution, but unfortunately I’m no regex ninja.

So far I have:

'1 20 3 400 5 60 7 800 9 0 '.sub(/(\d\* \d\* )/) {|s| s + “\n”}  
=\> "1 20 \n3 400 5 60 7 800 9 0 "

But how do I get the substitution to be ‘repeated’? Changing the regexp  
to /(\d\* \d\*)\*/ does not do what I want.

Also, I’m planning to run this on a large string, so I’d like it to be  
efficient if possible.

Thanks in advance

C

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 1:37pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/2 "2006-03-01T13:37:34Z")

</div>

On Wed, 2006-03-01 at 21:03 +0900, removed\_email\_address@domain.invalid wrote:

> Hi all
> 
> I have the string '1 20 3 400 5 60 7 800 9 0 ’ and need to replace  
> every n-th space in the string with another character. So if n=2 and  
> the replacement character is ‘\n’, then the above would become
> 
> ‘1 20\n3 400\n5 60\n7 800\n9 0\n’.
> 
> I’m sure it must be possible (easy, even) to do this with a regex  
> substitution, but unfortunately I’m no regex ninja.

There’s probably a better way to do this, but here’s a ‘metaregex’ idea:

```
str = "1 20 3 400 5 60 7 800 9 0 "
# => "1 20 3 400 5 60 7 800 9 0 "

n = 2
# => 2

r = Regexp.new('(' + ('\d+\s' * (n - 1)) + '\d+)(\s)')
# => /(\d+\s\d+)(\s)/

str.gsub(r) { $1 + rep }
# => "1 20\n3 400\n5 60\n7 800\n9 0\n"

n = 3
# => 3

r = Regexp.new('(' + ('\d+\s' * (n - 1)) + '\d+)(\s)')
# => /(\d+\s\d+\s\d+)(\s)/

str.gsub(r) { $1 + rep }
# => "1 20 3\n400 5 60\n7 800 9\n0 "
```

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 1:41pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/3 "2006-03-01T13:41:03Z")

</div>

On Wed, 2006-03-01 at 21:36 +0900, I forgot:

> There’s probably a better way to do this, but here’s a ‘metaregex’ idea:

- rep = “\n”

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 2:14pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/4 "2006-03-01T14:14:25Z")

</div>

Hi,

> > every n-th space in the string with another character. So if n=2 and
> 
> # =\> "1 20 3 400 5 60 7 800 9 0 "
> 
> n = 3
> 
> # =\> 3
> 
> r = Regexp.new(’(’ + (’\d+\s’ \* (n - 1)) + ‘\d+)(\s)’)
> 
> # =\> /(\d+\s\d+\s\d+)(\s)/
> 
> str.gsub® { $1 + rep }
> 
> # =\> "1 20 3\n400 5 60\n7 800 9\n0 "

Here’s another idea:

str = "1 20 3 400 5 60 7 800 9 0 "  
rep = “\n”  
n = 2  
str.gsub(/((\d+\s){#{n}})/){$1.chop+rep}

Regards,

Park H.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 2:33pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/5 "2006-03-01T14:33:35Z")

</div>

removed\_email\_address@domain.invalid wrote:

> Thanks in advance
> 
> C

How about:

text = '1 20 3 400 5 60 7 800 9 0 ’  
n = 2  
text.gsub!(/(\d+\s+){#{n-1}}(\d+)(\s+)/) { $1 + $2 + “\n” }

or completely different:

text = '1 20 3 400 5 60 7 800 9 0 ’  
n = 2  
i = 0  
text.gsub!(/\s+/) { |s| (i = (i+1) % n).zero? ? “\n” : s }

Robin

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 2:28pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/6 "2006-03-01T14:28:41Z")

</div>

Thanks all.

C

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 2:58pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/7 "2006-03-01T14:58:52Z")

</div>

removed\_email\_address@domain.invalid wrote:

> '1 20 3 400 5 60 7 800 9 0 '.sub(/(\d\* \d\* )/) {|s| s + “\n”}  
> =\> "1 20 \n3 400 5 60 7 800 9 0 "
> 
> But how do I get the substitution to be ‘repeated’? Changing the regexp  
> to /(\d\* \d\*)\*/ does not do what I want.

The answer you’re looking for is String#gsub:  
'1 20 3 400 5 60 7 800 9 0 '.gsub(/(\d\* \d\* )/) {|s| s + “\n”}  
=\> "1 20 \n3 400\n 5 60\n 7 800\n 9 0\n "

Cheers,  
Dave

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [March 1, 2006, 3:07pm UTC](https://www.ruby-forum.com/t/regex-replacement-problem-replace-every-n-th/54316/8 "2006-03-01T15:07:22Z")

</div>

On Wed, 2006-03-01 at 22:58 +0900, Dave B. wrote:

> removed\_email\_address@domain.invalid wrote:
> 
> > '1 20 3 400 5 60 7 800 9 0 '.sub(/(\d\* \d\* )/) {|s| s + “\n”}  
> > =\> "1 20 \n3 400 5 60 7 800 9 0 "
> > 
> > But how do I get the substitution to be ‘repeated’? Changing the regexp  
> > to /(\d\* \d\*)\*/ does not do what I want.
> 
> The answer you’re looking for is String#gsub:  
> '1 20 3 400 5 60 7 800 9 0 '.gsub(/(\d\* \d\* )/) {|s| s + “\n”}  
> =\> "1 20 \n3 400\n 5 60\n 7 800\n 9 0\n "

Well, that’ll teach me not to try and do stuff before my all-important  
Caffotine breakfast. I still had the extra \* on the end and couldn’t  
make it work… Duh ☹
