VScode - replace captured group with the values

Viewed 2230

i have a bunch of strings in code such as: <td style="background-color:#fdfdff">&nbsp;</td> and <td>&nbsp;</td> in one file.

The goal is to replace &nbsp; from first example with 0, while &nbsp; from second example with - (dash)

I'm using VScode regex, but I can't find the way to replace captured groups with specific values, as $1, $2 groups refer to original string groups. This one is just example, how I'm trying to achieve this, but VScode don't ignore grouped regex.

enter image description here

2 Answers

An alternative process is to use a snippet which can do conditional replacements. With this snippet:

    "replaceTDs": {
      "prefix": "tdr",    // whatever prefix you want 
      "body": [
        "${TM_SELECTED_TEXT/(?<=\">)(&nbsp;)|(&nbsp;)/${1:+0}${2:+-}/g}",
      ]
    }

The conditional replacements can be quite simple since you first find and select only the two alternative texts you are interested in. So

find: <td\s*(style="[^"]*"\s*)>&nbsp;</td>|<td>&nbsp;</td> old version

This simpler find will probably work for you:

<td\s*(style="[^"]*")?\s*>&nbsp;</td>

Don't replace, rather Control+Shift+L : selects all your two alternatives. Esc to focus on editor from the find widget.

Then apply your snippet, in this case type tdr+Tab

and all the changes are made. You just have to make the snippet one time and then do a single find.

td replacement demo


This technique scales a little better than running as many find/replaces as you have replacements to do. Even with more conditional replacements it would probably be a simple change to the one snippet to add more replacements.


Also you can simplify this even more if you use a keybinding to trigger your snippet (you don't have to change focus from the find widget - or create the separate snippet). So with no snippet, but this keybinding:

 {
    "key": "alt+w",
    "command": "editor.action.insertSnippet",
    "args": {
      "snippet": "${TM_SELECTED_TEXT/(?<=\">)(&nbsp;)|(&nbsp;)/${1:+0}${2:+-}/g}"  
    },
    "when": "editorHasSelection"
  }

now the same demo:

td replacement keybinding

You can use

  1. Search for (?<=<td\s+style="[^"]*">)&nbsp;(?=</td>) and replace with 0, and
  2. Search for <td>&nbsp;</td> and replace with <td>-</td>, no need for a regex here.

Note that capturing groups are meant to keep captured substrings.

The first pattern matches

  • (?<=<td\s+style="[^"]*">) - a place in string that is immediately preceded with <td, one or more whitespaces, style=", any zero or more chars other than " and then a >
  • &nbsp; - a literal string
  • (?=</td>) - immediately to the right, there must be </td>.
Related