Forum: Ruby Regex replacement problem---replace every n-th

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
C577f603b752a8a4f5cb34a423316a71?d=identicon&s=25 unknown (Guest)
on 2006-03-01 13:03
(Received via mailing list)
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
A9b6a93b860020caf9d2d1d58c32478f?d=identicon&s=25 Ross Bamford (Guest)
on 2006-03-01 13:37
(Received via mailing list)
On Wed, 2006-03-01 at 21:03 +0900, junk5@microserf.org.uk 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 "
A9b6a93b860020caf9d2d1d58c32478f?d=identicon&s=25 Ross Bamford (Guest)
on 2006-03-01 13:41
(Received via mailing list)
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"
E51d56251ec4affafe85ee9367228965?d=identicon&s=25 Park Heesob (Guest)
on 2006-03-01 14:14
(Received via mailing list)
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(r) { $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 Heesob
C577f603b752a8a4f5cb34a423316a71?d=identicon&s=25 unknown (Guest)
on 2006-03-01 14:28
(Received via mailing list)
Thanks all.

C
Cd49db0b676767ea4358b1047c4cddd2?d=identicon&s=25 Robin Stocker (Guest)
on 2006-03-01 14:33
(Received via mailing list)
junk5@microserf.org.uk 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
0b561a629b87f0bbf71b45ee5a48febb?d=identicon&s=25 Dave Burt (Guest)
on 2006-03-01 14:58
(Received via mailing list)
junk5@microserf.org.uk 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
A9b6a93b860020caf9d2d1d58c32478f?d=identicon&s=25 Ross Bamford (Guest)
on 2006-03-01 15:07
(Received via mailing list)
On Wed, 2006-03-01 at 22:58 +0900, Dave Burt wrote:
> junk5@microserf.org.uk 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 :(
This topic is locked and can not be replied to.