Search code examples
regexvisual-studio-coderepeatregex-groupregexp-replace

Matching pattern repeats for unknown times. How to replace each matched string?


I have this string

mark:: string1, string2, string3

I want it to be

mark:: xxstring1xx, xxstring2xx, xxstring3xx

The point is, I don't know how many times the matched string repeated. Sometimes there are 10 strings in the line, sometimes there is none. So far I have come up with this matching pattern mark:: ((.*)(, )+)*, but I'm unable to find a way to substitute individual matched string.

If possible I would like to have this output:

mark:: xxstring1xx
mark:: xxstring2xx
mark:: xxstring3xx

But if it's not possible it's fine to have the one-line solution


Solution

  • By using snippets you can make use of their ability to use conditionals.

    IF you can select the line first, this is quite easy. Use this keybinding in your keybindings.json:

    {
      "key": "alt+w",            // whatever keybinding you want
      "command": "editor.action.insertSnippet",
      "args": {
        "snippet": "${TM_SELECTED_TEXT/(mark::\\s*)|([^,]+)(, )?/$1${2:+xx}$2${2:+xx}$3/g}"
      }
    }
    

    The find is simple: (mark::\\s*)|([^,]+)(, )?

    replace: $1${2:+xx}$2${2:+xx}$3 Capture group 1 followed by xx if there is a group 2 ${2:+xx} : conditional, followed by group 2, followed by another conditional.

    Demo:

    snippet demo 1


    If you have a bunch of these lines in a file and you want to transform them all at once, then follow these steps:

    1. In the Find widget, Find: (mark::\s*)(.*)$ with the regex option enabled.
    2. Alt+Enter to select all matches.
    3. Trigger your snippet keybinding from above.

    Demo:

    snippet transform demo 2


    For your other version with separate lines for each entry, use this in the keybinding:

    {
      "key": "alt+w",
      "command": "editor.action.insertSnippet",
      "args": {
        // single line version 
        // "snippet": "${TM_SELECTED_TEXT/(mark::\\s*)|([^,]+)(, )?/$1${2:+xx}$2${2:+xx}$3/g}"
        
        // each on its own line
        "snippet": "${TM_SELECTED_TEXT/(mark::\\s*)|([^,]+)(, )?/${2:+mark:: }${2:+xx}$2${2:+xx}${3:+\n}/g}"
      }
    }
    

    snippet demo 3