Can this can be done in Vim?
What I mean is: searching for 'BadJob' and replacing with 'GoodJob' would do the following replacements 'badjob' -> 'goodjob' 'BadJob' -> 'GoodJob' 'badJob' -> 'goodJob' 'BADJOB' -> 'GOODJOB'
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 :)
:set ignorecase
. 2. Bad
will be substituted by GOOD
instead of Good
. 3. The "job
" part of the question is ignored, so this will also replace lambada
→ lamgooda
. Fixes and explanations for these bugs and a few other things in my answer. (Also LOLOWLs!)
For most (non-complex) cases, i recommend @rampion’s answer over mine.
If you got a minute, my post might be still be worthwhile, though. Level up your awareness for scripting gotchas.
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.
https://i.stack.imgur.com/99eI5.jpg
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](https://stackoverflow.com/questions/782511/case-preserving-substitute-in-vim/782617#782617), fixing a few shortcomings.
If you're only matching an exact (case-independent) string with a few possible capitalizations, another possibility is:
:s/abc/\={'abc':'xyz','Abc':'Xyz'}[submatch(0)]/i
An alternative to the keepcase plugin is SmartCase - replacing words while keeping original case. (Don't let yourself be discourage by the bad ratings.)
:%s/file\A\?size/\=SmartCase("LastModifiedTime")/ig
?
:SmartCase
command. I've extended that in my own fork. Note that this requires ingo-library as a dependency.
What about
:%s/\Cbadjob/goodjob/
:%s/\CBadJob/GoodJob/
:%s/\CbadJob/goodJob/
:%s/\CBADJOB/GOODJOB/
See: https://stackoverflow.com/a/2287449/5599687
Success story sharing
BadJob
and I want to replace it withGoodJob
, I can't use%S/badjob/goodjob/g
. It fails to detect a match.%S/BadJob/GoodJob/g
, then the Subvert command will switch to mixed-case mode and will do all the substitions as given by OP.%S
activate mixed-case mode, or does the input argumentBadJob
need to literally match the thing you're trying to replace? The former seems like strange ux, and the latter seems to defeat the purpose.