Search code examples
htmlregexvisual-studio-codereplacetags

How to change only certain elements, keeping intact other elements with the search module in VS Code?


I want to know how is it possible to change some HTML tag such as :

<tag1>[my text]</tag1>

to another type of tag such as :

<tag2>[my text]</tag2>

but keeping the inner text intact.

Because it is possible to get all elements with regEx, but how to tell VS code to keep the inner text intact ?

More generally, how to change only certain elements by keep other elements intact in the search module of VS Code ?

Thank you for your help.


Solution

  • Open the search

    CTRL + F to find, then click the down arrow or CTRL + H to open the replacing gui directly.

    How to do it

    Then in the search (first) input enter:

    <tag1>(\[my text\])</tag1>
    

    in the replacement (second) input enter:

    <tag2>$1</tag2>
    

    Explanations

    In the search (first) input:

    (\[my text\]): the () is a capturing group and is the first here.
    The value to capture is [my text] and the scare bracket are escaped \[.
    Maybe you wouldn't have square brackets and instead your regex would be <tag1>(my text)</tag1>.

    In the replacement (second) input:

    The $1 refer to the value of the first capturing group so [my text].

    To go further

    Below is a more practical case. Still using search and replacement regex.

    Search Regex:

    <tag1( +[^>]+)?>((?:.*\r?\n?)*)</tag1>
    

    This regex is used to find a specific tag <tag1> and its content, which will be replaced by another tag.

    • <tag1:
      Matches the literal string <tag1 at the start of the tag. This ensures the regex is looking for the specific opening tag.

    • ( +[^>]+)?:

      • +: Matches one or more spaces following the tag name. This ensures that attributes (if any) start after a space.
      • [^>]+: Matches one or more characters that are not the closing angle bracket (>), i.e., it matches any attributes within the opening <tag1 ... >.
      • ?: The whole group is optional, meaning the tag can either have attributes (like <tag1 class="something">) or no attributes (like <tag1>).
    • >:
      Matches the closing angle bracket (>), marking the end of the opening tag.

    • ((?:.*\r?\n?)*):

      • This part matches the content inside the <tag1></tag1> tags.
      • (?: ... ): A non-capturing group that matches:
        • .*: Any character (except line breaks), zero or more times.
        • \r?\n?: Optionally matches a carriage return (\r) and/or a newline (\n), which means this can handle both Windows (\r\n) and Unix (\n) style line endings.
      • *: The entire non-capturing group can repeat any number of times, effectively matching any text (with or without line breaks) within the <tag1> and </tag1> tags.
    • </tag1>:
      Matches the literal closing </tag1> tag.

    Capturing Groups:

    1. $1: Captures any attributes (or spaces) within the opening tag <tag1>. This corresponds to ( +[^>]+)?.
    2. $2: Captures the content inside the opening and closing tags <tag1></tag1>. This corresponds to ((?:.*\r?\n?)*).

    Replacement Regex:

    <tag2$1>$2</tag2>
    

    This replacement regex transforms the matched content:

    • <tag2$1>:
      Replaces <tag1> with <tag2>, while preserving any attributes from <tag1>. If there were attributes captured in $1, they would be included after <tag2.

    • $2:
      Inserts the content inside the original <tag1></tag1> tags into the new <tag2></tag2> tags.

    • </tag2>:
      Replaces the closing </tag1> tag with </tag2>.

    Example:

    Original Input:

    <tag1>[my text]</tag1>
    
    <tag1>some other text</tag1>
    
    <tag1></tag1>
    
    <tag1><atag>a tag between</atag></tag1>
    
    <tag1><amtag>
        a tag
        in multilines
        and a
        link <a href="http://www.stackoverflow.com"></a>
    </amtag></tag1>
    
    <tag1>some tags
         in multilines and a class
         <address><data value="sd
            addressdas
            data
            datad"></data></address>
    </tag1>
    
    <tag1 value="2">[my text]</tag1>
    
    <tag1 multi="2"
          lines="3"
          cls="5"
          >[my text]</tag1>
    

    After Replacement:

    <tag2>[my text]</tag2>
    
    <tag2>some other text</tag2>
    
    <tag2></tag2>
    
    <tag2><atag>a tag between</atag></tag2>
    
    <tag2><amtag>
        a tag
        in multilines
        and a
        link <a href="http://www.stackoverflow.com"></a>
    </amtag></tag2>
    
    <tag2>some tags
         in multilines and a class
         <address><data value="sd
            addressdas
            data
            datad"></data></address>
    </tag2>
    
    <tag2 value="2">[my text]</tag2>
    
    <tag2 multi="2"
          lines="3"
          cls="5"
          >[my text]</tag2>