Case preserving substitute in Vim

前端 未结 6 1822
無奈伤痛
無奈伤痛 2020-12-02 06:32

Can this can be done in Vim?

What I mean is: searching for \'BadJob\' and replacing with \'GoodJob\' would do the following replacements



        
相关标签:
6条回答
  • 2020-12-02 06:40

    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...

    0 讨论(0)
  • 2020-12-02 06:40

    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
    
    0 讨论(0)
  • 2020-12-02 06:42

    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 :)

    0 讨论(0)
  • 2020-12-02 06:48

    An alternative to the keepcase plugin is SmartCase - replacing words while keeping original case. (Don't let yourself be discourage by the bad ratings.)

    0 讨论(0)
  • 2020-12-02 06:55

    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.

    0 讨论(0)
  • 2020-12-02 07:00

    Use abolish.vim:

    :%S/badjob/goodjob/g
    
    0 讨论(0)
提交回复
热议问题