4

I'm having some trouble to find the right pattern to get the string I want.

My starting string is :

,,,,C3:,D3,E3,F3,,

I would like to have

      C3:  [D3,E3,F3]
  1. I would like to replace each starting commas by double space
  2. Replace coma after colon by double space and left square bracket
  3. Replace trailing commas by right square bracket

For now, I tried this :

> a = ",,,,C3:,D3,E3,F3,,"
=> ",,,,C3:,D3,E3,F3,,"
> b = a.gsub(/^,*/, "  ").gsub(/(?<=:),/, "  [").gsub(/[,]*$/,"" ).gsub(/[ ]*$/, "]")
=> "  C3:  [D3,E3,F3]"
> b == "        C3:  [D3,E3,F3]"
=> false

I can't reach to replace each starting comma by a double space to obtain 8 spaces in this case.

Could you help me to find the right regexp and if possible to improve my code, please ?

1

2 Answers 2

6

To replace each starting comma with a double space, you need to use \G operator, i.e. .gsub(/\G,/, ' '). That operator tells the regex engine to match at the start of the string and then after each successful match. So, you only replace each consecutive comma in the beginning of the string with .gsub(/\G,/, ' ').

Then, you can add other replacements:

s.gsub(/\G,/, ' ').sub(/,+\z/, ']').sub(/:,+/, ': [')

See the IDEONE demo

s = ",,,,C3:,D3,E3,F3,,"
puts s.gsub(/\G,/, '  ').sub(/,+\z/, ']').sub(/:,+/, ':  [')

Output:

        C3:  [D3,E3,F3]
Sign up to request clarification or add additional context in comments.

4 Comments

Thank You, I didn't know \G pattern.
FYI I also got rid of the lookbehind in one of your regexes, lookbehinds are rather costly regex subpatterns. Since you know the context (it is :), you can match it and then reinsert in the replacement pattern easily.
An alternative is ",,,hi".gsub(/^(,+)/, ' '*'\1'.size). I am puzzled, however, as to why this works without the capture group: ",,,hi".gsub(/^,+/, ' '*'\1'.size). (I did reload IRB before testing.)
@CarySwoveland: It does not work the way you think: '\1'.size is always 2 because the \1 is treated as a literal string. puts '\1'.size outputs 2, it will always be two. Here is an example of how to use a "callback" with Ruby's gsub - that would work, but it would involve more coding.
0

To construct the desired string, one needs to know:

  • the number of leading commas (the size of the string comprised of the leading commas)
  • the string following the leading commas up to and including the colon
  • the string between the comma following the colon and two or more commas

It is a simple matter to construct a regex that saves each of these three strings to a capture group:

r = /
    (,*)   # match leading commas in capture group 1
    (.+:)  # match up and including colon in capture group 2
    ,      # match comma     
    (.+)   # match any number of any characters in capture group 3
    ,,     # match two commas
    /x     # extended/free-spacing regex definition mode

",,,,C3:,D3,E3,F3,," =~ r

We can now form the desired string from the contents of the three capture groups:

"#{'  '*$1.size}#{$2} [#{$3}]"
  #=> "       C3: [D3,E3,F3]"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.