Reputation: 149
Given the following indented text:
two spaces
four
six
non-leading spaces
I'd like to convert every 2 leading spaces to a tab, essentially converting from soft tabs to hard tabs. I'm looking for the following result (using an 'x' instead of "\t"):
xtwo spaces
xxfour
xxxsix
non-leading spaces
What is the most efficient or eloquent way to do this in ruby?
What I have so far seems to be working, but it doesn't feel right.
input.gsub!(/^ {2}/,"x")
res = []
input.split(/\n/).each do |line|
while line =~ /^x+ {2}/
line.gsub!(/^(x+) {2}/,"\\1x")
end
res << line
end
puts res.join("\n")
I noticed the answer using sed and \G:
perl -pe '1 while s/\G {2}/\t/gc' input.txt >output.txt
But I can't figure out how to mimic the pattern in Ruby. This is as far as I got:
rep = 1
while input =~ /^x* {2}/ && rep < 10
input.gsub!(/\G {2}/,"x")
rep += 1
end
puts input
Upvotes: 4
Views: 546
Reputation:
Whats wrong with using (?:^ {2})|\G {2}
in multi-line mode?
The first match will always be at the beginning of the line,
then \G will match succesively right next to that, or the match
will fail. The next match will always be the beginning of the line.. repeats.
In Perl its $str =~ s/(?:^ {2})|\G {2}/x/mg;
or $str =~ s/(?:^ {2})|\G {2}/\t/mg;
input.gsub!(/(?:^ {2})|\G {2}/m,"x")
Edit: Of course the anchors can be factored out and put into an alternation
http://ideone.com/1oDOJ
input.gsub!(/(?:^|\G) {2}/m,"x")
Upvotes: 4
Reputation: 35318
You can just use a single gsub for that:
str.gsub(/^( {2})+/) { |spaces| "\t" * (spaces.length / 2) }
Upvotes: 2