Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Case preserving substitute in Vim

Tags:

replace

vim

People also ask

How do you replace a word in Vim?

Basic Find and Replace In Vim, you can find and replace text using the :substitute ( :s ) command. To run commands in Vim, you must be in normal mode, the default mode when starting the editor. To go back to normal mode from any other mode, just press the 'Esc' key.

How do you substitute in vi?

The % is a shortcut that tells vi to search all lines of the file for search_string and change it to replacement_string . The global ( g ) flag at the end of the command tells vi to continue searching for other occurrences of search_string . To confirm each replacement, add the confirm ( c ) flag after the global flag.


Use abolish.vim:

:%S/badjob/goodjob/g

I don't know if this is the kind of solution you're looking for... but i've used this: keepcase.vim

There's no support otherwise in vim...


sure u can

:s/\cbad/\= strpart(submatch(0), 0 ,1) == toupper(strpart(submatch(0), 0, 1)) ? "GOOD" : "good"/

ps. i'm guessing keepcase.vim encapsulates some similar logic :)


You can just paste and adapt this:
(Of course, if you do this from time to time, you will want a plugin instead of this monstrosity. But for some who are in a hurry and only need it once, this is a quick hack for your pasting pleasure:)

:%s/\cbad\zejob/\= ( submatch(0)[0] is# toupper(submatch(0)[0]) ? 'G' : 'g' ) . ( submatch(0)[1] is# toupper(submatch(0)[1]) ? 'OOD' : 'ood' )

Apart from the search pattern, you have to edit the four 'strings' in the replacement code: Edit the parts in bold:

:%s/\cbad\zejob/\=
( submatch(0)[0] is# toupper(submatch(0)[0]) ? 'G' : 'g' ) .
( submatch(0)[1] is# toupper(submatch(0)[1]) ? 'OOD' : 'ood' )

Don't use this 'orange' version for pasting, since its linebreak characters will also break the command.

/\ze is vim regex syntactic sugar for marking a positive lookahead: The pattern after \ze is checked for, but not substituted.


is#?? Let me explain… (If interested.)

# (also in ==# and others) enforces case sensitivity. Otherwise, with :set ignorecase (which I use, because that is required for the useful :set smartcase), vim will consider 'a' == 'A'!!

Crazy as it is, we really should account for it: Because it is user-settings-dependent, == should NEVAR be used! (Except where that would actually be what you want.) I will even follow the recommendation to use ==# when comparing integers: http://learnvimscriptthehardway.stevelosh.com/chapters/22.html#code-defensively

is# instead of ==# is another way of coding defensively: It improves type safety: http://google.github.io/styleguide/vimscriptguide.xml?showone=Type_checking#Type_checking
It should be used when comparing against a string literal.

'single-quoted' instead of "double quoted" strings are another good practice: http://google.github.io/styleguide/vimscriptguide.xml?showone=Strings#Strings


HT @fc. - this answer builds on their answer, fixing a few shortcomings.