在Vim中删除包含特定文本的行的有效方法

fcg9iug3  于 2022-11-11  发布在  其他
关注(0)|答案(4)|浏览(342)

目前我可以搜索文本。

/text

然后使用dd删除行,如果我不想删除,我可以使用n进行下一个匹配。
"但还有更快的方法吗"
下面这个命令删除了所有包含文本的行,但问题是它一次删除了所有行,有时文本在某些行中是例外。

:g/text/d

但是我想要简单的东西比如

:%s/text/some_other_text/gc

因为这提供了替换或不替换的选项。

w41d8nur

w41d8nur1#

您不需要全局命令来执行此操作。

  • 添加通配符
  • 和添加行尾。
    示例
%s/.*text.*\n//gc
k75qkfdt

k75qkfdt2#

您可以混合使用:help global:help substitute

:g/text/s/.*\n//c

在删除包含text的每一行之前,将要求确认:

xuo3flqw

xuo3flqw3#

我试图找到一种使用global:substitute的方法,它可以正确处理连续行上的匹配和第一行上的匹配,但是唉,我没有灵感。
所以,我回到了我的基本:我已经实现了我认为缺少的东西::confirm global .
The result has been pushed in my library plugin
工作原理:
1.我准备了一个有状态的变量,它在重要的时候会记住以前的用户选择(alwaysquit,或者 last)。

  • 我在模式上执行global,对于每个匹配,我检查用户希望做什么。
  • 我要么使用“不再询问”状态
  • 或者我要求使用StatusLineNC突出显示组和echo "\rmessage" + :redraw。这是一个非常古老的技巧,甚至在Vim 6 IIRC之前我们就已经使用过了。

相关代码如下:

" Function: lh#ui#ask(message) {{{3
function! lh#ui#ask(message) abort
  redraw! " clear the msg line
  echohl StatusLineNC
  echo "\r".a:message
  echohl None
  let key = nr2char(getchar())
  return key
endfunction

" Function: lh#ui#confirm_command(command) {{{3
" states:
" - ask
" - ignore
" - always
function! s:check() dict abort
  if     self.state == 'ignore'
    return
  elseif self.state == 'always'
    let shall_execute_command = 1
  elseif self.state == 'ask'
    try
      let cleanup = lh#on#exit()
            \.restore('&cursorline')
            \.restore_highlight('CursorLine')
      set cursorline
      hi CursorLine   cterm=NONE ctermbg=black ctermfg=white guibg=black guifg=white
      let choice = lh#ui#ask(self.message)
      if     choice == 'q'
        let self.state = 'ignore'
        let shall_execute_command = 0
        " TODO: find how not to blink
        redraw! " clear the msg line
      elseif choice == 'a'
        let self.state = 'always'
        let shall_execute_command = 1
        " TODO: find how not to blink
        redraw! " clear the msg line
      elseif choice == 'y'
        " leave state as 'ask'
        let shall_execute_command = 1
      elseif choice == 'n'
        " leave state as 'ask'
        let shall_execute_command = 0
      elseif choice == 'l'
        let shall_execute_command = 1
        let self.state = 'ignore'
      endif
    finally
      call cleanup.finalize()
    endtry
  endif

  if shall_execute_command
    execute self.command
  endif
endfunction

function! s:getSID() abort
  return eval(matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_getSID$'))
endfunction
let s:k_script_name      = s:getSID()

function! lh#ui#make_confirm_command(command, message) abort
  let res = lh#object#make_top_type(
        \ { 'state': 'ask'
        \ , 'command': a:command
        \ , 'message': a:message . ' (y/n/a/q/l/^E/^Y)'
        \ })
  call lh#object#inject_methods(res, s:k_script_name, 'check')
  return res
endfunction

" Function: lh#ui#global_confirm_command(pattern, command, message [, sep='/']) {{{3
" Exemple: to remove lines that match a pattern:
" > call lh#ui#global_confirm_command(pattern, 'd', 'delete line?')
function! lh#ui#global_confirm_command(pattern, command, message, ...) abort
  let cmd = lh#ui#make_confirm_command(a:command, a:message)
  let sep = get(a:, 1, '/')
  exe 'g'.sep.a:pattern.sep.'call cmd.check()'
endfunction

" Function: lh#ui#_confirm_global(param) {{{3
function! lh#ui#_confirm_global(param) abort
  let sep = a:param[0]
  let parts = split(a:param, sep)
  if len(parts) < 2
    throw "Not enough arguments to `ConfirmGlobal`!"
  endif
  let cmd = join(parts[1:])
  call lh#ui#global_confirm_command(parts[0], cmd, cmd . ' on line?', sep)
endfunction

command! -nargs=1 ConfirmGlobal call lh#ui#_confirm_global('<args>')

您可以在此处键入:

  • :call lh#ui#global_confirm_command(pattern, 'd', 'delete line?')
  • :ConfirmGlobal/pattern/d,它生成的提示信息较少
guykilcj

guykilcj4#

最有效的方法是合并:glboal和:norm

:g/test/norm dd

相关问题