2009-08-19 55 views
10

我有一個帶有退格字符的日誌文件(^ H)。我正在瀏覽Vim中的文件,可能很難看到發生了什麼。如何在文本文件中「應用」退格字符(最好在vim中)

理想情況下,我希望能夠在給定的行/範圍上「應用」所有^ H,以便我可以看到最終結果。

我寧願在一行一行的基礎上在Vim中完成這項工作,但是轉換整個文件的解決方案總比沒有好。

+0

出於好奇,^ H字符的用途是什麼?他們打算在打印輸出或控制檯上達到什麼目的? – 2009-08-19 09:23:13

+0

@John Saunders:在老式的打印機上,他們造成了疊印,允許您通過重複來加粗:x^Hx^Hx^Hx或下劃線:_^Ha_^Hb_^Hc。在Linux上使用「less」來表示這些文本,並以粗體或下劃線顯示文本(也許它仍然會這樣!) – 2009-08-19 11:05:25

+0

它仍然有效:$ echo'h_^Hell^Hlo'|更少 – 2009-08-19 11:07:11

回答

12

打開的「粘貼」選項(使用:set paste),然後按dd i <CTRL-R> 1 <ESC>上要退格將應用到每一行。這也適用於刪除多行或甚至整個文件的情況。

這裏的關鍵是,你在插入模式下使用<CTRL-R> 1爲「打出來」寄存器1(其中已刪除線剛剛投入)的內容,和「粘貼」選項阻止Vim中使用任何映射或縮寫。

+1

謝謝!我記錄了這個(qa),所以我可以將它應用於@a – Draemon 2009-08-19 09:37:24

+1

Clever。我喜歡。 – 2009-08-27 07:27:41

+0

爲了做多行,第二個'd'應該改變。例如,要完成一個100行文件,請將光標放在最上面,然後'd 100 ' – jnovack 2013-10-23 13:27:32

0

只要刪除所有出現的^ H(這裏是正則表達式的解釋。):

:s/.^H//g 

(插入2 H字面上按下Ctrl-V CTRL-H)

這會適用於當前行。如果您想將其應用於其他線路,請使用您想要的任何範圍。

一旦你做了一個:s...命令,你可以只輸入:sg(你需要到g上月底重新應用到所有出現在當前行)重複另一條線路上。

+0

這不適用於「somethadr^h^h^h^hing hing」 – Draemon 2009-08-19 09:34:22

+1

這不會根據要求「申請」退格。我們需要刪除^ H應該退格的字符。 – 2009-08-27 07:29:16

+0

你沒看到正則表達式中的點嗎?我同意它不處理一串退格字符,但它確實刪除了退格字符的字符。 – camh 2009-08-27 08:59:31

8

簡單化的答案:

:%s/[^^H]^H//g 

其中^^ H是:

  1. 文字字符^
  2. 按Ctrl-V CTRL-H

,並重復幾次(直到vim會告訴你沒有進行替換

如果你想不重複的,你不介意使用的perl%:

%!perl -0pe 's{([^\x08]+)(\x08+)}{substr$1,0,-length$2}eg' 

所有的人物都是字面 - 即你沒有做CTRL-V ...在上面一行的任何地方!

應該在大多數情況下工作。

+0

我喜歡它,但我想知道是否有一種方式,而不必重複它(當然不與正則表達式) – Draemon 2009-08-19 11:21:36

+0

當然,在這裏你有它:) – 2009-08-19 12:25:56

+0

'[^^ H]'似乎不正確。它不會匹配任何既不是'^也不是'H'的字符嗎?更類似'[。\ a](?<!^ H)^ H'(注意:測試過的筆記)似乎更加正確......('\ a'匹配字符串的開頭,其中'^ H'應該是吞嚥我相信。) – eyelidlessness 2010-01-26 22:25:20

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> 
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 

或者在管道中使用它(「say」是Mac上的語音轉文本應用程序)

man date | ./crush | say 

可以粉碎複製到您喜愛的可執行文件的目錄(在/ usr/local/bin目錄,或一些這樣的),然後引用它,如下所示

man date | crush | say 
8

我GOOGLE了這一點的同時試圖記住命令我以前曾用過'申請'退格,然後我記得它:col -b - 這裏是manpage。 (它確實多了一點,來自BSD或者更確切地說AT &牛逼UNIX的手冊頁說,所以,如果你是在Linux上,你可能需要在bsdmainutils安裝額外的包,在Debian的。)

+0

你是上帝! – JeffG 2011-03-31 14:06:01

+0

你贏了線程:) – Joe 2011-11-21 20:31:32

0

這裏有一個基於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輸入

0

這裏的一個快得多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

相關問題