Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search and replace across multiple lines with conversion to lower case in Vim

Here's what I'd like to do, for each one of many files:

  • search for all occurrences of <a href then begin block selection
  • select until the first occurrence of >
  • convert the entire match to lowercase
like image 298
Olivier Pons Avatar asked May 18 '10 15:05

Olivier Pons


People also ask

How to change to lowercase in Vim?

Visual select the text, then U for uppercase or u for lowercase. To swap all casing in a visual selection, press ~ (tilde). Without using a visual selection, gU<motion> will make the characters in motion uppercase, or use gu<motion> for lowercase. For more of these, see Section 3 in Vim's change.

How do you change multiple words in Vim?

Change and repeat Search for text using / or for a word using * . In normal mode, type cgn (change the next search hit) then immediately type the replacement. Press Esc to finish. From normal mode, search for the next occurrence that you want to replace ( n ) and press . to repeat the last change.

How do I select a word in Vim?

You can use * and/or # to search for the word under the cursor or viw to visually select the word under the cursor.


1 Answers

Check it out:

s/<a href\(\_[^>]*\)>/<a href\L\1>/

This says: match <a href, followed by zero or more characters besides >, including newlines (indicated by \_), and then finally a >. Replace it with <a href, the captured text converted to lowercase (indicated by \L), and the trailing >.

Obviously you're on your own if there's a > somewhere inside your tag, but such is life.

(And in case it's not clear, you'll use this as :%s/.../... or :<range>s/.../.../ for some smaller range.)

To use this on multiple files, you'll use windo, bufdo, or tabdo (depending on whether the files are open as tabs, windows, or just as buffers). There's a lot of documentation out there:

  • a previous question
  • a Vim tip
  • the vim help

In general, it'll probably look something like this:

:tabdo <range>s/.../.../
:windo <range>s/.../.../
:bufdo <range>s/.../.../ | w

I've added a write command to the bufdo version, because it can't move on to the next buffer without saving the current one. You could do this for the others too, if you wanted to write immediately, but they'll work without. It's up to you to get all the files open - the easiest way is just vim <lots of files> to get them as buffers, or vim -o <lots of files> to get them as windows (use -O to split vertically instead of horizontally).

like image 84
Cascabel Avatar answered Sep 21 '22 00:09

Cascabel