vim:转义字符串以进行替换(vim脚本)
vim: escaping strings for substitution (vimscript)
我目前在vim.
中写一个经常需要编程的替代函数
我已经写的函数看起来像这样 运行 基本上可以搜索和替换里面没有任何特殊字符的字符串。我已经意识到自动转义“/”。我的问题是,如何调整
行中的 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:
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
更新
我设法转义了很多这样的字符
escape(searchPattern, ' / \') . '/' . escape(replacePattern, ' / \')
但是我怎么知道我必须转义哪个字符列表,如果基本上可能的话,每个字符都可以在搜索和替换字符串中?
要执行 文字替换,请指定 "very-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'
这并不能完全回答您的问题,而是另一种看待您要解决的问题的方式。我并不完全遵循 :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
开始录制'a'宏'
:%s/this/that/g
启动宏并将 'that' 替换为 'this'。 (按回车键)
:w|cnf
写入文件并转到下一个(按回车键)
q
停止录制 'a' 宏。
然后qb@a@bq
将运行宏一次,保存在@b
中。然后 运行
(type) @b
再一次,它会一直调用自己直到完成。
我目前在vim.
中写一个经常需要编程的替代函数我已经写的函数看起来像这样 运行 基本上可以搜索和替换里面没有任何特殊字符的字符串。我已经意识到自动转义“/”。我的问题是,如何调整
行中的 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:
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
更新
我设法转义了很多这样的字符
escape(searchPattern, ' / \') . '/' . escape(replacePattern, ' / \')
但是我怎么知道我必须转义哪个字符列表,如果基本上可能的话,每个字符都可以在搜索和替换字符串中?
要执行 文字替换,请指定 "very-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'
这并不能完全回答您的问题,而是另一种看待您要解决的问题的方式。我并不完全遵循 :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
开始录制'a'宏'
:%s/this/that/g
启动宏并将 'that' 替换为 'this'。 (按回车键)
:w|cnf
写入文件并转到下一个(按回车键)
q
停止录制 'a' 宏。
然后qb@a@bq
将运行宏一次,保存在@b
中。然后 运行
(type) @b
再一次,它会一直调用自己直到完成。