我有一個帶有退格字符的日誌文件(^ H)。我正在瀏覽Vim中的文件,可能很難看到發生了什麼。如何在文本文件中「應用」退格字符(最好在vim中)
理想情況下,我希望能夠在給定的行/範圍上「應用」所有^ H,以便我可以看到最終結果。
我寧願在一行一行的基礎上在Vim中完成這項工作,但是轉換整個文件的解決方案總比沒有好。
我有一個帶有退格字符的日誌文件(^ H)。我正在瀏覽Vim中的文件,可能很難看到發生了什麼。如何在文本文件中「應用」退格字符(最好在vim中)
理想情況下,我希望能夠在給定的行/範圍上「應用」所有^ H,以便我可以看到最終結果。
我寧願在一行一行的基礎上在Vim中完成這項工作,但是轉換整個文件的解決方案總比沒有好。
打開的「粘貼」選項(使用:set paste
),然後按dd i <CTRL-R> 1 <ESC>
上要退格將應用到每一行。這也適用於刪除多行或甚至整個文件的情況。
這裏的關鍵是,你在插入模式下使用<CTRL-R> 1
爲「打出來」寄存器1(其中已刪除線剛剛投入)的內容,和「粘貼」選項阻止Vim中使用任何映射或縮寫。
只要刪除所有出現的^ H(這裏是正則表達式的解釋。):
:s/.^H//g
(插入2 H字面上按下Ctrl-V CTRL-H)
這會適用於當前行。如果您想將其應用於其他線路,請使用您想要的任何範圍。
一旦你做了一個:s...
命令,你可以只輸入:sg
(你需要到g上月底重新應用到所有出現在當前行)重複另一條線路上。
簡單化的答案:
:%s/[^^H]^H//g
其中^^ H是:
,並重復幾次(直到vim會告訴你沒有進行替換
如果你想不重複的,你不介意使用的perl%:
%!perl -0pe 's{([^\x08]+)(\x08+)}{substr$1,0,-length$2}eg'
所有的人物都是字面 - 即你沒有做CTRL-V ...在上面一行的任何地方!
應該在大多數情況下工作。
我喜歡它,但我想知道是否有一種方式,而不必重複它(當然不與正則表達式) – Draemon 2009-08-19 11:21:36
當然,在這裏你有它:) – 2009-08-19 12:25:56
'[^^ H]'似乎不正確。它不會匹配任何既不是'^也不是'H'的字符嗎?更類似'[。\ a](?<!^ H)^ H'(注意:測試過的筆記)似乎更加正確......('\ a'匹配字符串的開頭,其中'^ H'應該是吞嚥我相信。) – eyelidlessness 2010-01-26 22:25:20
以下功能如何?我使用了\%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>
好吧,這裏是一個裸機解決方案。
複製這些代碼到一個名爲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
或者在管道中使用它(「say」是Mac上的語音轉文本應用程序)
man date | ./crush | say
可以粉碎複製到您喜愛的可執行文件的目錄(在/ usr/local/bin目錄,或一些這樣的),然後引用它,如下所示
man date | crush | say
這裏有一個基於bash的過濾器,你可以用它來處理整個文件:
#!/bin/bash
while read LINE; do
while [[ "$LINE" =~ '^H' ]]; do
LINE="${LINE/[^^H]^H/}"
done
echo "$LINE"
done
注意,如果2 H出現,它是使用CTRL-v CTRL-H進入VIM和^^^h作爲SHIFT-6 CTRL-v CTRL-h輸入。
這裏的一個快得多awk中過濾,做同樣的:
#!/usr/bin/awk -f
function crushify(data) {
while (data ~ /[^^H]^H/) {
gsub(/[^^H]^H/, "", data)
}
print data
}
crushify($0)
注意,其中^^ħ出現時,在^^ħ第一插入符號是插入符號(換檔-6)和通過鍵入CTRL-V輸入(進入vim)第二個字符H CTRL-H
出於好奇,^ H字符的用途是什麼?他們打算在打印輸出或控制檯上達到什麼目的? – 2009-08-19 09:23:13
@John Saunders:在老式的打印機上,他們造成了疊印,允許您通過重複來加粗:x^Hx^Hx^Hx或下劃線:_^Ha_^Hb_^Hc。在Linux上使用「less」來表示這些文本,並以粗體或下劃線顯示文本(也許它仍然會這樣!) – 2009-08-19 11:05:25
它仍然有效:$ echo'h_^Hell^Hlo'|更少 – 2009-08-19 11:07:11