[regex] How can I make my match non greedy in vim?

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?

This question is related to regex vim regex-greedy

The answer is


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.


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

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

just try:

:help non-greedy

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,


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


What's wrong with

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

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>

With \v (as suggested in several comments)

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

Examples related to regex

Why my regexp for hyphenated words doesn't work? grep's at sign caught as whitespace Preg_match backtrack error regex match any single character (one character only) re.sub erroring with "Expected string or bytes-like object" Only numbers. Input number in React Visual Studio Code Search and Replace with Regular Expressions Strip / trim all strings of a dataframe return string with first match Regex How to capture multiple repeated groups?

Examples related to vim

Why does using from __future__ import print_function breaks Python2-style print? How to run vi on docker container? How can I install MacVim on OS X? Find and replace strings in vim on multiple lines Running Python code in Vim How do I set the default font size in Vim? Move cursor to end of file in vim Set encoding and fileencoding to utf-8 in Vim How to select all and copy in vim? Why I've got no crontab entry on OS X when using vim?

Examples related to regex-greedy

How to capture multiple repeated groups? How can I write a regex which matches non greedy? Regex credit card number tests What is the difference between .*? and .* regular expressions? How to do a non-greedy match in grep? How to make Regular expression into non-greedy? What do 'lazy' and 'greedy' mean in the context of regular expressions? How can I make my match non greedy in vim? Non greedy (reluctant) regex matching in sed? Python non-greedy regexes