我有一个带有退格字符的日志文件(^ H)。我正在查看Vim中的文件,很难看到发生了什么。
理想情况下,我希望能够“应用”给定行/范围内的所有^ H,以便我可以看到最终结果。
我宁愿在Vim中逐行进行此操作,但是转换整个文件的解决方案总比没有好。
答案 0 :(得分:12)
启用“粘贴”选项(使用 :set paste
),然后在要应用的每一行上按 dd i <CTRL-R> 1 <ESC>
退格到。如果删除多行,甚至整个文件,这也有效。
这里的关键是你在插入模式下使用 <CTRL-R> 1
来“输出”寄存器1的内容(你的删除行刚被放入)和'粘贴'选项可防止Vim使用任何映射或缩写。
答案 1 :(得分:9)
我试图记住我之前用来“应用”退格键的命令,然后我记得它: col -b - 这里是manpage。 (它更多地来自BSD或者更确切地说是AT&amp; T UNIX,如联机帮助页所示,所以如果你在Linux上,你可能需要在 bsdmainutils 上的debian上安装一个额外的软件包。 )
答案 2 :(得分:8)
简单回答:
:%s/[^^H]^H//g
其中^^ H是:
并重复几次(直到vim会告诉你没有替换
如果您不想重复,并且不介意使用%!perl:
%!perl -0pe 's{([^\x08]+)(\x08+)}{substr$1,0,-length$2}eg'
所有字符都是字面的 - 即您不必在上面的任何位置执行ctrl-v ...
在大多数情况下应该有效。
答案 3 :(得分:1)
好的,这是一个裸机解决方案。
将此代码复制到名为crush.c的文件中:
#include <stdio.h>
// crush out x^H sequences
// there was a program that did this, once
// cja, 16 nov 09
main()
{
int c, lc = 0;
while ((c = getchar()) != EOF) {
if (c == '\x08')
lc = '\0';
else {
if (lc)
putchar(lc);
lc = c;
}
}
if (lc)
putchar(lc);
}
使用您最喜欢的编译器编译此代码:
gcc crush.c -o crush
然后像这样使用它来粉碎那些麻烦的序列:
./crush <infilename >outfilename
或者在管道中使用它(“说”是Mac上的语音到文本应用程序)
man date | ./crush | say
您可以将crush复制到您喜欢的可执行文件目录(/ usr / local / bin或其他类似文件),然后按如下方式引用它
man date | crush | say
答案 4 :(得分:0)
只需删除所有出现的。^ H(其中。是。的正则表达式解释):
:s/.^H//g
(通过输入Ctrl-V Ctrl-H逐字插入^ H)
这将适用于当前行。如果要将其应用于其他行,请使用您想要的任何范围。
完成一个:s...
命令后,只需键入:sg
即可在另一行重复(您需要在结尾处重新应用于当前行上的所有匹配项)。 / p>
答案 5 :(得分:0)
以下功能怎么样?我使用\%x08而不是^ H,因为它更容易复制和粘贴生成的代码。您可以输入并使用 Ctrl - V Ctrl - H 如果您愿意,但我认为\% x08可能更容易。这也试图在行的开头处理退格(它只删除它们)。
" Define a command to make it easier to use (default range is whole file)
command! -range=% ApplyBackspaces <line1>,<line2>call ApplyBackspaces()
" Function that does the work
function! ApplyBackspaces() range
" For each line in the selected lines
for index in range(a:firstline, a:lastline)
" Get the line as a string
let thisline = getline(index)
" Remove backspaces at the start of the line
let thisline = substitute(thisline, '^\%x08*', '', '')
" Repeatedly apply backspaces until there are none left
while thisline =~ '.\%x08'
" Substitute any character followed by backspace with nothing
let thisline = substitute(thisline, '.\%x08', '', 'g')
endwhile
" Remove any backspaces left at the start of the line
let thisline = substitute(thisline, '^\%x08*', '', '')
" Write the line back
call setline(index, thisline)
endfor
endfunction
使用:
" Whole file:
:ApplyBackspaces
" Whole file (explicitly requested):
:%ApplyBackspaces
" Visual range:
:'<,'>ApplyBackspaces
有关详细信息,请参阅:
:help command
:help command-range
:help function
:help function-range-example
:help substitute()
:help =~
:help \%x
修改
请注意,如果您想在一行上工作,可以执行以下操作:
" Define the command to default to the current line rather than the whole file
command! -range ApplyBackspaces <line1>,<line2>call ApplyBackspaces()
" Create a mapping so that pressing ,b in normal mode deals with the current line
nmap ,b :ApplyBackspaces<CR>
或者您可以这样做:
nmap ,b :.ApplyBackspaces<CR>
答案 6 :(得分:0)
这是一个基于Bash的过滤器,可用于处理整个文件:
#!/bin/bash
while read LINE; do
while [[ "$LINE" =~ '^H' ]]; do
LINE="${LINE/[^^H]^H/}"
done
echo "$LINE"
done
请注意,出现 ^ H 的地方,使用CTRL-v CTRL-h将其输入vim,输入 ^^ H 作为SHIFT-6 CTRL- v CTRL-h。
答案 7 :(得分:0)
这是一个更快的Awk过滤器,可以做同样的事情:
#!/usr/bin/awk -f
function crushify(data) {
while (data ~ /[^^H]^H/) {
gsub(/[^^H]^H/, "", data)
}
print data
}
crushify($0)
请注意, ^^ H 出现时, ^^ H 中的第一个插入符号为插入符号(shift-6),第二个插入符号为 H <通过键入CTRL-v CTRL-H
输入/ em>(进入vim)