Jimmy Pitts
Jimmy Pitts

Reputation: 2382

vim case insensitive search with sensitive replace

I have a file with this in it:

test
Test

Currently, if If I want to replace all cases of 'test' with 'foo', and 'Test' with 'Foo', I have to use two commands:

:%s/test/foo/g
:%s/Test/Foo/g

Is there any way that I can accomplish this with a single command?

Upvotes: 36

Views: 12455

Answers (2)

Nathan Chappell
Nathan Chappell

Reputation: 2436

As my granpappy used to say, for every plugin there's a vim one-liner that's just as good. Try

%s/\(test\|Test\)/\=submatch(0) =~ '^\l.*' ? 'foo' : 'Foo'/g

Explanation:

%s/ substitute over the whole buffer

\(test\|Test\)/ match for 'test' OR 'Test'

\= Make the substitute string use whatever the following expression evaluates to

submatch(0) In this context evaluates to the entire matched expression

=~ '\l.*' String-comparison for regex match (against a word starting with a lowercase letter)

... ? 'foo' : 'Foo' if-then-else expression which evaluates to 'foo' if ... is true, 'Foo' otherwise

/g Do this over the entire line

With slight modifications this should be more than enough to satisfy our needs. References:

:help :s
:help :sub-replace-\=
:help expression

...I just want to put a little warning for anyone who tries to get into vim evaluations and expressions... They are very counter-intuitive (I come from a C++ background, maybe if you come from bash or python it's less of an issue). I found the following vimscript guide/ self-teaching lessons to be extremely helpful: http://learnvimscriptthehardway.stevelosh.com/

Upvotes: 15

epsilonhalbe
epsilonhalbe

Reputation: 15967

I think this vim plugin by tim pope will solve your problem, install it and %Subvert/{t}est/{f}oo/g or %Subvert/test/foo/g (thanks for the comment) will do the trick

Upvotes: 16

Related Questions