DonovanChan
DonovanChan

Reputation: 149

Convert leading spaces to tabs in ruby

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

Answers (2)

user557597
user557597

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;

Ruby http://ideone.com/oZ4Os

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

d11wtq
d11wtq

Reputation: 35318

You can just use a single gsub for that:

str.gsub(/^( {2})+/) { |spaces| "\t" * (spaces.length / 2) }

Upvotes: 2

Related Questions