在分析大型日志文件时,我经常删除包含不相关文本的行:
:g/whatever/d
有时候我会发现文本跨越多行,比如stacktraces。为此,我记录下所采取的步骤(search,go to start锚,delete to end anchor),然后用100000@q重新运行那个宏。我正在搜索vim已经包含的一个函数或特性,它允许我标记文本并删除包含该文本的所有行。理想情况下,这也适用于块选择。
100000@q
hwamh0ep1#
如果我没理解错你的问题,这个命令应该能完成你想要的任务:
: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
:h edit-paragraph-join
join
d
yvt65v4c2#
:g/whatever/d2
将删除包含whatever的行及其后面的行。如果您可以找到总是出现在第一行的文本,则可以通过将2更改为您需要的任何值来去除后面所有具有相同行数的文本。
whatever
2
3xiyfsfu3#
你实际上可以只使用一些普通的命令在一个全局命令,以实现你想要的,看看你的例子(希望我理解它或多或少的权利):
someText NullPointerException ... omitted
你想从NPE上面的行删除到omitted的行,对吗?
NPE
omitted
:g/NullPointerException/execute "normal! kddd/omitted\<cr>dd"
它可能看起来很复杂,但实际上并不复杂。它并不比宏好,但我更喜欢命令,因为我在录制宏时总是出错。因为它只使用正常的vim动作,所以很容易采用。如果你不知道你以前的锚在哪里,你可以使用?anchor\<cr>代替kd。为了更好地演示,你必须提交一个现实的例子。[1]您可能会说,这只需要运行一次,但对于递归宏http://vim.wikia.com/wiki/Record_a_recursive_macro也是如此
?anchor\<cr>
kd
lndjwyie4#
感谢这里的答案,我能够编写一个非常方便的函数:下面的源代码使用户可以选择文本并删除所有具有相同(或类似的)文本在当前的缓冲区。这与两行和多行选择工作。正如我所说,我正在寻找的东西,使我更快地分析日志文件。日志文件通常包含日期和时间,这些变化的所有时间,所以我们最好能忽略数字,让我们看看,我用了这两个Map:
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()代码。
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
谢谢,艾普斯巴克,奥斯瓦尔多医生和肯特。
4条答案
按热度按时间hwamh0ep1#
如果我没理解错你的问题,这个命令应该能完成你想要的任务:
示例:
之前:
之后:
请阅读
:h edit-paragraph-join
,该命令有很好的解释,您的情况只是将join
更改为d
yvt65v4c2#
将删除包含
whatever
的行及其后面的行。如果您可以找到总是出现在第一行的文本,则可以通过将2
更改为您需要的任何值来去除后面所有具有相同行数的文本。3xiyfsfu3#
你实际上可以只使用一些普通的命令在一个全局命令,以实现你想要的,看看你的例子(希望我理解它或多或少的权利):
你想从
NPE
上面的行删除到omitted
的行,对吗?它可能看起来很复杂,但实际上并不复杂。它并不比宏好,但我更喜欢命令,因为我在录制宏时总是出错。
因为它只使用正常的vim动作,所以很容易采用。如果你不知道你以前的锚在哪里,你可以使用
?anchor\<cr>
代替kd
。为了更好地演示,你必须提交一个现实的例子。[1]您可能会说,这只需要运行一次,但对于递归宏http://vim.wikia.com/wiki/Record_a_recursive_macro也是如此
lndjwyie4#
感谢这里的答案,我能够编写一个非常方便的函数:下面的源代码使用户可以选择文本并删除所有具有相同(或类似的)文本在当前的缓冲区。这与两行和多行选择工作。正如我所说,我正在寻找的东西,使我更快地分析日志文件。日志文件通常包含日期和时间,这些变化的所有时间,所以我们最好能忽略数字,让我们看看,我用了这两个Map:
典型用法:
下面是源代码:
我从this answer中提取了
GetVisualSelection()
代码。谢谢,艾普斯巴克,奥斯瓦尔多医生和肯特。