Vim으로 바이너리 파일을 편집하는 방법?


77

어떤 종류의 16 진 모드에서 이진 파일을 편집하는 방법이 있습니까?

예를 들어 나는에 의해 도시 일부 이진 데이터가있는 경우 xxd또는 hexdump -C같은를 :

$ hexdump -C a.bin | head -n 5
00000000  cf fa ed fe 07 00 00 01  03 00 00 80 02 00 00 00  |................|
00000010  12 00 00 00 40 05 00 00  85 00 20 00 00 00 00 00  |....@..... .....|
00000020  19 00 00 00 48 00 00 00  5f 5f 50 41 47 45 5a 45  |....H...__PAGEZE|
00000030  52 4f 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |RO..............|
00000040  00 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|

$ xxd a.bin | head -n 5
0000000: cffa edfe 0700 0001 0300 0080 0200 0000  ................
0000010: 1200 0000 4005 0000 8500 2000 0000 0000  ....@..... .....
0000020: 1900 0000 4800 0000 5f5f 5041 4745 5a45  ....H...__PAGEZE
0000030: 524f 0000 0000 0000 0000 0000 0000 0000  RO..............
0000040: 0000 0000 0100 0000 0000 0000 0000 0000  ................

특정 위치에서 값을 변경하려면이 종류의보기가 올바른 위치를 찾는 데 도움이됩니다 (예 : 변경할 위치가 알려진 문자열 근처에있을 때).

답변:


89

가장 간단한 방법은 binary옵션 을 사용하는 것입니다. 보낸 사람 :help binary:

This option should be set before editing a binary file.  You can also
use the -b Vim argument.  When this option is switched on a few
options will be changed (also when it already was on):
        'textwidth'  will be set to 0
        'wrapmargin' will be set to 0
        'modeline'   will be off
        'expandtab'  will be off
Also, 'fileformat' and 'fileformats' options will not be used, the
file is read and written like 'fileformat' was "unix" (a single <NL>
separates lines).
The 'fileencoding' and 'fileencodings' options will not be used, the
file is read without conversion.

[..]

When writing a file the <EOL> for the last line is only written if
there was one in the original file (normally Vim appends an <EOL> to
the last line if there is none; this would make the file longer).  See
the 'endofline' option.

이 작업을 수행하지 않고 환경에서 멀티 바이트 인코딩 (예 : 대부분의 사람들이 사용하는 UTF-8)을 사용하는 경우 Vim은 텍스트를 그대로 인코딩하려고 시도하여 일반적으로 파일 손상을 일으 킵니다.

파일을 열고을 사용하여이를 확인할 수 있습니다 :w. 이제 변경되었습니다.
사용자가 설정 한 경우 LANGLC_ALLC(ASCII), 빔 아무것도 변환하지 않고 파일이 동일하게 유지 빔은 어떤 멀티 바이트 인코딩을 수행 할 필요가 없습니다 때문에 (여전히하지만, 줄 바꿈을 추가합니다).

개인적 으로 바이너리 를 비활성화 하는 것을 선호 set wrap하지만 다른 사람들이 바이너리를 활성화 하는 것을 선호 할 수도 있습니다 . YMMV. 또 다른 유용한 방법은입니다 :set display=uhex. 보낸 사람 :help 'display':

uhex            Show unprintable characters hexadecimal as <xx>
                instead of using ^C and ~C.

마지막 팁으로 %B( :set rulerformat=0x%B) 를 사용하여 눈금자의 커서 아래에있는 문자의 16 진수 값을 표시 할 수 있습니다 .

더 고급 : xxd

xxd(1)도구를 사용하여 파일을보다 읽기 쉬운 형식으로 변환하고 (이것이 중요한 비트입니다) 편집 된 "읽기 가능한 형식"을 구문 분석 한 다음 이진 데이터로 다시 쓸 수 있습니다. xxd의 일부 vim이므로 vim설치 한 경우 설치해야합니다 xxd.

그것을 사용하려면 :

$ xxd /bin/ls | vi -

또는 이미 파일을 연 경우 다음을 사용할 수 있습니다.

:%!xxd

이제 화면 왼쪽의 16 진수 (16 진수)에서 변경해야하며 오른쪽의 변경 (인쇄 가능한 표현)은 쓰기시 무시됩니다.

저장하려면 다음을 사용하십시오 xxd -r.

:%!xxd -r > new-ls

파일이에 저장됩니다 new-ls.

또는 현재 버퍼에 바이너리를로드하려면

:%!xxd -r

보낸 사람 xxd(1):

   -r | -revert
          reverse operation: convert (or patch) hexdump into  binary.   If
          not  writing  to stdout, xxd writes into its output file without
          truncating it. Use the combination -r -p to read plain hexadeci‐
          mal dumps without line number information and without a particu‐
          lar column layout. Additional  Whitespace  and  line-breaks  are
          allowed anywhere.

그런 다음 사용 :w하여 작성하십시오. ( 주의 : binary 위와 같은 이유로 파일에 쓰기 전에 옵션 을 설정하려고합니다 ).

이를보다 쉽게하기위한 보완 키 바인딩 :

" Hex read
nmap <Leader>hr :%!xxd<CR> :set filetype=xxd<CR>

" Hex write
nmap <Leader>hw :%!xxd -r<CR> :set binary<CR> :set filetype=<CR>

gVim을 사용하는 경우 '도구 ➙ HEX로 변환'및 '도구 ➙ 다시 변환'아래에있는 메뉴에서도 사용할 수 있습니다.

정력 팁 위키는 더 많은 정보와 헬퍼 스크립트가있는 페이지가 있습니다. 개인적으로 바이너리 파일을 자주 편집하는 경우 실제 16 진수 편집기를 사용하는 것이 좋습니다. Vim 일종의 일을 할 있지만 분명히 그것을 위해 설계된 것은 아니며 :set binaryVim 없이 쓰면 바이너리 파일이 손상 될 수 있습니다!


4
사랑스러운 대답이지만 아마도 "집에서 이것을 시도하지 마십시오!"
msw

바이트를 제거해야하는 경우 어떻게합니까? 예를 들어 바이너리의 중간에.
Anton K

Vim 이하는 일을 모르겠지만 아무것도 변경하지 않았지만 200KB 바이너리 파일에 95KB의 텍스트를 추가하고 있습니다. 와도 :set binary noeol fenc=utf-8. 실제로, 파일이 말하기 전에 파일을 열 자마자 바로 수행합니다 [noeol] [converted]. vim이 버퍼를 150 % 더 크게 만들어야하는 이유는 무엇입니까? 그런 파일이 손상되는 것을 어떻게 방지합니까?
Braden Best

작동하는 유일한 방법은 :r !xxd <file>(나 $ xxd <file> | vim -) 읽기, 그리고 :w !xxd -r > <file>쓰기,하지만이 적합하지 않습니다.
Braden Best

훌륭한 답변입니다. 축복의 URL이 작동하지 않습니다. github github.com/bwrsandman/Bless 에서 찾았습니다 .
sonofagun

19

16 진보기에서 2 진 파일의 내용을 보려면 파일을 열고 2 진 모드를 켜고 다음 xxd명령을 통해 버퍼를 필터링하십시오 .

:set binary
:%!xxd

왼쪽 영역을 변경하고 (16 진수 편집) 준비가되면를 통해 필터링 xxd -r하고 파일을 마지막으로 저장할 수 있습니다.

:%!xxd -r
:w

열기 및 닫기 전에 필터링 단계가 번거롭고 .bin확장명 이있는 파일로이 작업을 수행하는 경우이를 vimrc에 추가하여 프로세스를 자동으로 만들 수 있습니다.

" for hex editing
augroup Binary
  au!
  au BufReadPre  *.bin let &bin=1
  au BufReadPost *.bin if &bin | %!xxd
  au BufReadPost *.bin set ft=xxd | endif
  au BufWritePre *.bin if &bin | %!xxd -r
  au BufWritePre *.bin endif
  au BufWritePost *.bin if &bin | %!xxd
  au BufWritePost *.bin set nomod | endif
augroup END

나는 다음 지침을 따르 경우 (이진 파일을 열고 :%!xxd, :%!xxd -r, :w후 기록 된 바이너리 파일이며, didnt가 변경할!) 하지 ... 원본과 동일한이 당신의 경우 (내가 테스트입니다 /bin/ls). :set binary저장하기 전에 사용해야합니다 (또한 이유를 설명하는 답을 참조하십시오) ... 아마도 vimrc에 문제가 있습니까? 그러나 set binary
그럼에도 불구하고

1
당신은 대신에 추가 할 수 있습니다 augroup에 스크립트를 ~/.vim/plugin/binary.vim당신이 당신의 어수선하지 않으려면.vimrc
thom_nic

설치 외국에있는 경우, 그 augroup Binary목록은 다음 위치에 :help hex-editing또는 :help using-xxd5.5 이후 어떤 빔에 SEP (1999).
bb010g

6

"bvi"편집기를 사용하십시오. http://bvi.sourceforge.net/ (모든 Linux 저장소에 있습니다.)

$ apt-cache show bvi
[snip]
Description-en: binary file editor
 The bvi is a display-oriented editor for binary files, based on the vi
 text editor. If you are familiar with vi, just start the editor and begin to
 edit! If you never heard about vi, maybe bvi is not the best choice for you.

1
더 진보 된 대안은 vim 컨트롤을 가진 bviplus입니다.
Anton K


3

TL; DR 답변

이진 모드에서 Vim을 사용하여 파일을 엽니 다.

vim -b <file_to_edit>

Vim에서 다음과 같이 16 진 편집 모드로 들어가십시오.

:%!xxd -p

저장하려면 :

:%!xxd -p -r
:w

버퍼를 16 진 모드에서 다시 변환 한 다음 파일을 정상과 같이 저장합니다.

-p 옵션을 참고하십시오. 이것은 모든 여분의 인쇄 가능 주소와 보풀을 피하고 16 진수를 보여줍니다. 추가 컨텍스트를 원하면 -p를 생략하십시오.

파일을 저장할 때 파일의 끝에 (보통 의도하지 않은) LF 문자가 추가되므로 이진 모드가 아닌 Vim을 사용하여 파일을 열 때주의하십시오.


이것은 실제로 다른 답변에없는 것을 추가하지 않습니다.
Herb Wolfe

5
실제 TL; DR은 :h using-xxd그 이후로 v7.0001그리고 그 이후로 더 오랫동안 존재 해 왔습니다 . 사람들이 문서를 검색하면이 사이트의 활동이 줄어 듭니다.
Tommy A

1

이것은 자동으로 앞뒤로 쓰는 임시 파일을 사용하여 작업을 수행하는 편리한 작은 vim 플러그인처럼 보입니다.

몇 년 전에 필자가 사용하기에 적합하고 개선 한 유사한 플러그인을 발견했습니다. 누군가가 원하는 경우 여기에 관련 코드를 포함 시켰습니다. xxd 도구를 기반으로합니다. 위의 링크 된 GitHub 버전이 더 잘 작동한다고 확신하지만 실제로 직접 사용하지는 않았으므로 확실히 작동하는 것으로 알고있는 버전을 게시하는 것으로 나타났습니다.

이 다른 버전의 소스는 vim wikia, 특히이 페이지 였습니다.

코드는 다음과 같습니다.

"-------------------------------------------------------------------------------  
" Hexmode  
"-------------------------------------------------------------------------------  
" Creates an automatic hex viewing mode for vim by converting between hex dump  
" and binary formats. Makes editing binary files a breeze.  
"-------------------------------------------------------------------------------  
" Source: vim.wikia.com/wiki/Improved_Hex_editing  
" Author: Fritzophrenic, Tim Baker  
" Version: 7.1  
"-------------------------------------------------------------------------------  
" Configurable Options {{{1  
"-------------------------------------------------------------------------------  

" Automatically recognized extensions  
let s:hexmode_extensions = "*.bin,*.exe,*.hex"  

"-------------------------------------------------------------------------------
" Commands and Mappings {{{1
"-------------------------------------------------------------------------------

" ex command for toggling hex mode - define mapping if desired
command! -bar Hexmode call ToggleHex()
command! -nargs=0 Hexconfig edit $VIM\vimfiles\plugin\hexmode.vim | exe "normal 11G" | exe "normal zo"

nnoremap <C-H> :Hexmode<CR>
inoremap <C-H> <Esc>:Hexmode<CR>
vnoremap <C-H> :<C-U>Hexmode<CR>

"-------------------------------------------------------------------------------    
" Autocommands {{{1  
"-------------------------------------------------------------------------------  

if exists("loaded_hexmode")  
    finish  
endif  
let loaded_hexmode = 1  

" Automatically enter hex mode and handle file writes properly  
if has("autocmd")  
  " vim -b : edit binary using xxd-format  
  augroup Binary  
    au!  

    " set binary option for all binary files before reading them  
    exe "au! BufReadPre " . s:hexmode_extensions . " setlocal binary"

    " if on a fresh read the buffer variable is already set, it's wrong
    au BufReadPost *
          \ if exists('b:editHex') && b:editHex |
          \   let b:editHex = 0 |
          \ endif

    " convert to hex on startup for binary files automatically
    au BufReadPost *
          \ if &binary | Hexmode | endif

    " When the text is freed, the next time the buffer is made active it will
    " re-read the text and thus not match the correct mode, we will need to
    " convert it again if the buffer is again loaded.
    au BufUnload *
          \ if getbufvar(expand("<afile>"), 'editHex') == 1 |
          \   call setbufvar(expand("<afile>"), 'editHex', 0) |
          \ endif

    " before writing a file when editing in hex mode, convert back to non-hex
    au BufWritePre *
          \ if exists("b:editHex") && b:editHex && &binary |
          \  let oldro=&ro | let &ro=0 |
          \  let oldma=&ma | let &ma=1 |
          \  silent exe "%!xxd -r" |
          \  let &ma=oldma | let &ro=oldro |
          \  unlet oldma | unlet oldro |
          \ endif

    " after writing a binary file, if we're in hex mode, restore hex mode
    au BufWritePost *
          \ if exists("b:editHex") && b:editHex && &binary |
          \  let oldro=&ro | let &ro=0 |
          \  let oldma=&ma | let &ma=1 |
          \  silent exe "%!xxd" |
          \  exe "set nomod" |
          \  let &ma=oldma | let &ro=oldro |
          \  unlet oldma | unlet oldro |
          \ endif
  augroup END  
endif  

"-------------------------------------------------------------------------------
" Functions {{{1
"-------------------------------------------------------------------------------

" helper function to toggle hex mode
function! ToggleHex()
  " hex mode should be considered a read-only operation
  " save values for modified and read-only for restoration later,
  " and clear the read-only flag for now
  let l:modified=&mod
  let l:oldreadonly=&readonly
  let &readonly=0
  let l:oldmodifiable=&modifiable
  let &modifiable=1
  if !exists("b:editHex") || !b:editHex
    " save old options
    let b:oldft=&ft
    let b:oldbin=&bin
    " set new options
    setlocal binary " make sure it overrides any textwidth, etc.
    let &ft="xxd"
    " set status
    let b:editHex=1
    " switch to hex editor
    set sh=C:/cygwin/bin/bash
    %!xxd
  else
    " restore old options
    let &ft=b:oldft
    if !b:oldbin
      setlocal nobinary
    endif
    " set status
    let b:editHex=0
    " return to normal editing
    %!xxd -r
  endif
  " restore values for modified and read only state
  let &mod=l:modified
  let &readonly=l:oldreadonly
  let &modifiable=l:oldmodifiable
endfunction

" vim: ft=vim:fdc=2:fdm=marker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.