How can I make my match non greedy in vim?

RegexVimRegex Greedy

Regex Problem Overview


I have a big HTML file that has lots of markup that looks like this:

<p class="MsoNormal" style="margin: 0in 0in 0pt;">
  <span style="font-size: small; font-family: Times New Roman;">stuff here</span>
</p>

I'm trying to do a Vim search-and-replace to get rid of all class="" and style="" but I'm having trouble making the match ungreedy.

My first attempt was this

%s/style=".*?"//g

but Vim doesn't seem to like the ?. Unfortunately removing the ? makes the match too greedy.

How can I make my match ungreedy?

Regex Solutions


Solution 1 - Regex

Instead of .* use .\{-}.

%s/style=".\{-}"//g

Also, see :help non-greedy

Solution 2 - Regex

Non greedy search in vim is done using {-} operator. Like this:

%s/style=".\{-}"//g

just try:

:help non-greedy

Solution 3 - Regex

What's wrong with

%s/style="[^"]*"//g

Solution 4 - Regex

If you're more comfortable PCRE regex syntax, which

  1. supports the non-greedy operator ?, as you asked in OP; and

  2. doesn't require backwhacking grouping and cardinality operators (an utterly counterintuitive vim syntax requirement since you're not matching literal characters but specifying operators); and

  3. you have [g]vim compiled with perl feature, test using

    :ver and inspect features; if +perl is there you're good to go)

try search/replace using

:perldo s///

Example. Swap src and alt attributes in img tag:

<p class="logo"><a href="/"><img src="/caminoglobal_en/includes/themes/camino/images/header_logo.png" alt=""></a></p>

:perldo s/(src=".*?")\s+(alt=".*?")/$2 $1/

<p class="logo"><a href="/"><img alt="" src="/caminoglobal_en/includes/themes/camino/images/header_logo.png"></a></p>

Solution 5 - Regex

I've found that a good solution to this type of question is:

:%!sed ...
(or perl if you prefer). IOW, rather than learning vim's regex peculiarities, use a tool you already know. Using perl would make the ? modifier work to ungreedy the match.

Solution 6 - Regex

With \v (as suggested in several comments)

:%s/\v(style|class)\=".{-}"//g

Solution 7 - Regex

Plugin eregex.vim handles Perl-style non-greedy operators *? and +?

Solution 8 - Regex

G'day,

Vim's regexp processing is not too brilliant. I've found that the regexp syntax for sed is about the right match for vim's capabilities.

I usually set the search highlighting on (:set hlsearch) and then play with the regexp after entering a slash to enter search mode.

Edit: Mark, that trick to minimise greedy matching is also covered in Dale Dougherty's excellent book "Sed & Awk" (sanitised Amazon link).

Chapter Three "Understanding Regular Expression Syntax" is an excellent intro to the more primitive regexp capabilities involved with sed and awk. Only a short read and highly recommended.

HTH

cheers,

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMark BiekView Question on Stackoverflow
Solution 1 - RegexRandy MorrisView Answer on Stackoverflow
Solution 2 - Regexuser80168View Answer on Stackoverflow
Solution 3 - RegexPaul TomblinView Answer on Stackoverflow
Solution 4 - RegexFrDarrylView Answer on Stackoverflow
Solution 5 - RegexWilliam PursellView Answer on Stackoverflow
Solution 6 - RegexJJoaoView Answer on Stackoverflow
Solution 7 - RegexbainView Answer on Stackoverflow
Solution 8 - RegexRob WellsView Answer on Stackoverflow