Mark Biek
Mark Biek

Reputation: 150759

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?

Upvotes: 594

Views: 171206

Answers (8)

Rob Wells
Rob Wells

Reputation: 37103

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.

Update: vim's regexp processing is greatly improved since I wrote the above. Especially when you learn about the "magic" and "very magic" switches in searches. See :help magic for the details.

HTH

cheers,

Upvotes: -4

bain
bain

Reputation: 2092

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

Upvotes: 6

JJoao
JJoao

Reputation: 5347

With \v (as suggested in several comments)

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

Upvotes: 6

user80168
user80168

Reputation:

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

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

just try:

:help non-greedy

Upvotes: 76

FrDarryl
FrDarryl

Reputation: 321

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>

Upvotes: 21

Randy Morris
Randy Morris

Reputation: 40927

Instead of .* use .\{-}.

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

Also, see :help non-greedy

Upvotes: 920

William Pursell
William Pursell

Reputation: 212248

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.

Upvotes: 14

Paul Tomblin
Paul Tomblin

Reputation: 182782

What's wrong with

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

Upvotes: 50

Related Questions