在分析大型日志文件时,我经常删除包含我认为不相关的文本的行:
:g/whatever/d
有时我发现跨越多行的文本,比如堆栈跟踪。为此,我记录了所采取的步骤(搜索,开始锚点,删除结束锚点)并用100000@q
重播该宏。我正在搜索已包含的功能或功能,允许我标记文本并删除包含此文本的所有行。理想情况下,这也适用于块选择。
答案 0 :(得分:3)
如果我理解你的问题,这个命令应该做你想要的:
:g/NullPointer/,/omitt/d
示例:
1
2
3
NullPointerException1
4
5
6
omitted
7
NullPointerException2
8
9
omitted
10
1
2
3
7
10
请阅读:h edit-paragraph-join
,该命令有很好的解释,您的情况只是将join
更改为d
答案 1 :(得分:2)
:g/whatever/d2
将删除whatever
行及其后面的行。如果您可以找到始终在第一行中出现的文本,则可以通过将2
更改为您需要的任何内容来删除所有以下文本(如果它具有相同的行数)。
答案 2 :(得分:2)
你实际上可以在全局命令中使用一些普通命令来实现你想要的,看看你的例子(希望我理解它或多或少):
someText
NullPointerException
...
omitted
您希望从NPE
上方的行中删除,直到omitted
的行正确?
只需使用以下内容:
:g/NullPointerException/execute "normal! kddd/omitted\<cr>dd"
它可能看起来很复杂,但事实并非如此。它并不比宏 1 更好 ,但我更喜欢命令,因为我总是记录宏的错误。
由于它只使用普通的vim运动,因此很容易采用。如果你f.e.不知道您以前的锚点在哪里,您可以使用?anchor\<cr>
代替kd
。为了更好的演示,你必须提交一个现实的例子。
[1]你可以说,这只需要运行一次,但对于递归宏http://vim.wikia.com/wiki/Record_a_recursive_macro
也是如此。答案 3 :(得分:1)
感谢这里的答案,我能够编写一个非常方便的函数:下面的源代码可以选择文本并删除当前缓冲区中具有相同(或类似)文本的所有行。这适用于在线和多线选择。正如我所说,我正在寻找能够让我更快地分析日志文件的东西。日志文件通常包含日期和时间,并且这些日期和时间一直在变化,因此最好有一些让我们忽略数字的东西。让我们来看看。我正在使用这两个映射:
vnoremap d :<C-U>echo RemoveSelectionFromBuffer(0)<CR>
vnoremap D :<C-U>echo RemoveSelectionFromBuffer(1)<CR>
典型用法:
这是源代码:
" Removes lines matching the selected text from buffer.
function! RemoveSelectionFromBuffer(ignoreNumbers)
let lines = GetVisualSelection() " selected lines
" Escape backslashes and slashes (delimiters)
call map(lines, {k, v -> substitute(v, '\\\|/', '\\&', 'g')})
if a:ignoreNumbers == 1
" Substitute all numbers with \s*\d\s* - in formatted output matching
" lines may have whitespace instead of numbers. All backslashes need
" to be escaped because \V (very nomagic) will be used.
call map(lines, {k, v -> substitute(v, '\s*\d\+\s*', '\\s\\*\\d\\+\\s\\*', 'g')})
endif
let blc = line('$') " number of lines in buffer (before deletion)
let vlc = len(lines) " number of selected lines
let pattern = join(lines, '\_.') " support multiline patterns
let cmd = ':g/\V' . pattern . '/d_' . vlc " delete matching lines (d_3)
let pos = getpos('v') " save position
execute "silent " . cmd
call setpos('.', pos) " restore position
let dlc = blc - line('$') " number of deleted lines
let dmc = dlc / vlc " number of deleted matches
let cmd = substitute(cmd, '\(.\{50\}\).*', '\1...', '') " command output
let lout = dlc . ' line' . (dlc == 1 ? '' : 's')
let mout = '(' . dmc . ' match' . (dmc == 1 ? '' : 'es') . ')'
return printf('%s removed: %s', (vlc == 1 ? lout : lout . ' ' . mout), cmd)
endfunction
我从this answer获取了GetVisualSelection()
代码。
function! GetVisualSelection()
if mode() == "v"
let [line_start, column_start] = getpos("v")[1:2]
let [line_end, column_end] = getpos(".")[1:2]
else
let [line_start, column_start] = getpos("'<")[1:2]
let [line_end, column_end] = getpos("'>")[1:2]
end
if (line2byte(line_start)+column_start) > (line2byte(line_end)+column_end)
let [line_start, column_start, line_end, column_end] =
\ [line_end, column_end, line_start, column_start]
end
let lines = getline(line_start, line_end)
if len(lines) == 0
return ''
endif
let lines[-1] = lines[-1][: column_end - 1]
let lines[0] = lines[0][column_start - 1:]
return lines
endfunction
谢谢,aepksbuck,DoktorOSwaldo和Kent。