Replace N spaces at the beginning of a line with N characters

Viewed 169

I am looking for a regex substitution to transform N white spaces at the beginning of a line to N  . So this text:

list:
  - first

should become:

list:
  - first

I have tried:

str = "list:\n  - first"
str.gsub(/(?<=^) */, "&nbsp;")

which returns:

list:
&nbsp;- first

which is missing one &nbsp;. How to improve the substitution to get the desired output?

4 Answers

You could make use of the \G anchor and \K to reset the starting point of the reported match.

To match all leading single spaces:

(?:\R\K|\G) 
  • (?: Non capture group
    • \R\K Match a newline and clear the match buffer
    • | Or
    • \G Assert the position at the end of the previous match
  • ) Close non capture group and match a space

See a regex demo and a Ruby demo.


To match only the single leading spaces in the example string:

(?:^.*:\R|\G)\K 

In parts, the pattern matches:

  • (?: Non capture group
    • ^.*:\R Match a line that ends with : and match a newline
    • | Or
    • \G Assert the position at the end of the previous match, or at the start of the string
  • ) Close non capture group
  • \K Forget what is matched so far and match a space

See a regex demo and a Ruby demo.

Example

re = /(?:^.*:\R|\G)\K /
str = 'list:
  - first'
result = str.gsub(re, '&nbsp;')

puts result

Output

list:
&nbsp;&nbsp;- first

I would write

"list:\n  - first".gsub(/^ +/) { |s| '&nbsp;' * s.size }
  #=> "list:\n&nbsp;&nbsp;- first"

See String#*

Use gsub with a callback function:

str = "list:\n  - first"
output = str.gsub(/(?<=^|\n)[ ]+/) {|m| m.gsub(" ", "&nbsp;") }

This prints:

list:
&nbsp;&nbsp;- first

The pattern (?<=^|\n)[ ]+ captures one or more spaces at the start of a line. This match then gets passed to the callback, which replaces each space, one at a time, with &nbsp;.

You can use a short /(?:\G|^) / regex with a plain text &nbsp; replacement pattern:

result = text.gsub(/(?:\G|^) /, '&nbsp;')

See the regex demo. Details:

  • (?:\G|^) - start of a line or string or the end of the previous match
  • - a space.

See a Ruby demo:

str = "list:\n  - first"
result = str.gsub(/(?:\G|^) /, '&nbsp;')
puts result
# => 
#  list:
#  &nbsp;&nbsp;- first

If you need to match any whitespace, replace with a \s pattern. Or use \h if you need to only match horizontal whitespace.

Related