I want to replace html tags in vim but reuse what I found. Namely I want to replace

<div class="subSectionTitle">
   Title 1 


   Title 1 

I tried to use the s/pattern/replacement/ but somehow the string is not insert. After running

:%s/<div class="subSectionTitle">\_.\{-}<\/div>/<h1>\1<\/h1>/g

only get


could some one explain how the wildcard characters work in vim and why the \1 is not my desired text?

1 Answer 1

  • The . only matches normal characters, but no newlines. As your HTML tag spans multiple lines, there are no matches. Use the \_. atom instead (:help /\_.).
  • You reference the inner text with \1 inside the replacement, but don't actually capture it. To do that, enclose in \(...\):
  • The greedy match via * will match the first start tag and the last end tag, other tags will be gobbled up in the capture group, so this will only work with a single occurrence. To change all occurrences, use a non-greedy match by replacing * with \{-}. (Or use the second alternative.)
:%s/<div class="subSectionTitle">\(\_.\{-}\)<\/div>/<h1>\1<\/h1>/g

Alternatively, you can just match starting and end tags separately. (Even the original single match wouldn't handle replacing the corresponding closing tag in case of nested tags, anyway.) Instead of capturing the different beginnings of start and end tags, I instead start the actual match via the special /\zs atom.

:%s/<\zsdiv class="subSectionTitle">\|<\/zsdiv>/h1>/g
  • Thanks for the reply. Unfortunately when I run you command the first occurrence of the div is found and replace the very last div of the document.
    – A.Dumas
    Commented Dec 18, 2019 at 14:51
  • 1
    Right, another problem with your original attempt. (I see you've corrected that part of the question already.) The second alternative given doesn't have this problem, though. I've amended the answer. Commented Dec 18, 2019 at 15:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .