2017-09-15 254 views
1

我目前正在编写一个替代函数,我通常需要在vim中进行编程。vim:转义替换字符串(vimscript)

我已经写过的函数看起来像这样,并且对于搜索和替换内部没有任何特殊字符的字符串基本上可以运行。我已经意识到要自动逃避“/”。我的问题是,我怎么有这样自动适应所有的escape()函数在该行

execute ':silent :argdo %s/' . escape(searchPattern, '/') . '/' . escape(replacePattern, '/') . '/ge' 

有转义将被转义字符的?

" MAIN FUNCTION 
" inspired by http://vimcasts.org/episodes/project-wide-find-and-replace/ 
function! SubstituteProjectwide(searchInput) 
    :set hidden 
    let cwd = getcwd() 
    let filename=expand('%:p') 
    call inputsave() 
    let searchPattern = input('Search for: ', a:searchInput) 
    let replacePattern = input('Replace "' . searchPattern . '" with: ') 
    let filePattern = input('Filepattern: ', cwd . '/**/*.*') 
    call inputrestore() 
    execute ':silent :args ' . filePattern 
    execute ':silent :vimgrep /' . searchPattern . '/g ##' 
    execute ':silent :Qargs' 
    execute ':silent :argdo %s/' . escape(searchPattern, '/\') . '/' . escape(replacePattern, '/\') . '/ge' 
    execute ':silent :edit ' . filename 
    echo 'Replaced "' . searchPattern . '" with "' . replacePattern . '" in ' . filePattern 
endfunction 

" VISUAL ENTRYPOINT WITH SELECTED TEXT 
function! SubstituteProjectwideVisual() 
    let v = @* 
    call SubstituteProjectwide(GetVisualSelectedText()) 
endfunction 
:vnoremap <F6> :call SubstituteProjectwideVisual()<cr> 

" NORMAL ENTRYPOINT WIHT WORD UNDER CURSOR 
function! SubstituteProjectwideNormal() 
    let wordUnderCursor = expand("<cword>") 
    call SubsituteProjectwide(wordUnderCursor) 
endfunction 
:nnoremap <F6> :call SubstituteProjectwideNormal()<cr> 

" GETTING THE FILES WICH CONTAIN SEARCH PATTERN 
" copied from http://vimcasts.org/episodes/project-wide-find-and-replace/ 
command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames() 
function! QuickfixFilenames() 
    let buffer_numbers = {} 
    for quickfix_item in getqflist() 
    let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr']) 
    endfor 
    return join(map(values(buffer_numbers), 'fnameescape(v:val)')) 
endfunction 

" GETTING THE CURRENT VISUAL SELECTION 
" copied from: https://stackoverflow.com/questions/1533565/how-to-get-visually-selected-text-in-vimscript 
function! GetVisualSelectedText() 
    let [line_start, column_start] = getpos("'<")[1:2] 
    let [line_end, column_end] = getpos("'>")[1:2] 
    let lines = getline(line_start, line_end) 
    if len(lines) == 0 
    return '' 
    endif 
    let lines[-1] = lines[-1][: column_end - (&selection == 'inclusive' ? 1 : 2)] 
    let lines[0] = lines[0][column_start - 1:] 
    return join(lines, "\n") 
endfunction 

UPDATE

我设法逃脱众多人物像

escape(searchPattern, '/\') . '/' . escape(replacePattern, '/\') 

但是我怎么知道我必须逃离这角色的列表中,当它基本上是可能的,每一个字符可以在搜索和替换字符串?

回答

1

要执行字面取代,指定 “非常-nomagic”(:help /\V),和逃脱分离器(/)和在源\

如果设置了'magic'选项,则在替换中,&~也必须转义。 (\V已经不在这里工作。)

execute ':silent :argdo %s/\V' . escape(searchPattern, '/\') . '/' . escape(replacePattern, '/\' . (&magic ? '&~' : '')) . '/ge' 

断行(如果可能)必须从^M改为\n

execute ':silent :argdo %s/\V' . substitute(escape(searchPattern, '/\'),"\n",'\\n','ge') . '/' . escape(replacePattern, '/\' . (&magic ? '&~' : '')) . '/ge' 
+0

似乎运行。我必须用一些更复杂的搜索条件来测试它 – divramod

+0

@divramod请记住,您还需要转义'&'和'〜',至少在替换模式中。在@ ingo-karkat的答案中查看最后一行的结尾。 –

1

这并不完全回答你的问题,但是是另一种方式看着你想解决的问题。我并不完全遵循:args设置为您做的事情,因为quickfix在:vimgrep之后提供了所有您需要的信息。

我有这个在我的vimrc:

nnoremap <F3> :vimgrep // $PROJECT_ROOT_DIR/src/**/*.{cpp,h,c,inl,msg}<C-Left><C-Left><Right> 

显然,您要自定义的搜索路径,因为这样的重点就在以上五个文件扩展名在每次都配置一个特定的文件层次我推出Vim ...

无论如何,一旦你有了这个,:cr确保你在开始,然后做搜索&取代你想要的宏里面。如果你想,你可以在前几个测试中进行测试,但是...

qbq清除'b'寄存器。

qa开始录制的“一个”宏观”

:%s/this/that/g启动宏和替代‘说’的‘本’。(按回车键)

:w|cnf写文件,去到下一个(按回车键)

q停止记录的“a”宏。

然后[email protected]@bq将运行宏一次,将其保存在@b。然后只需运行 (类型)@b一次,直到它完成它会继续自称。