Vim ile ikili dosyalar nasıl düzenlenir?


77

İkili dosyaları bir tür onaltılık modda düzenlemenin bir yolu var mı?

Örneğin, bunun tarafından gösterilen xxdveya bunun hexdump -Cgibi bazı ikili verilerim varsa :

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

Değeri belirli bir pozisyonda değiştirmek istersem, bu tür bir bakış açısı, örneğin değiştirilecek pozisyonun bilinen bir dizgeye yakın olduğu durumlarda doğru yeri bulmasına yardımcı olacaktır.

Yanıtlar:


89

En basit yol binaryseçeneği kullanmaktır . Kimden :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.

Bunu yapmazsanız ve ortamınız çok baytlı bir kodlama kullanıyorsa (örneğin, çoğu insanın kullandığı gibi UTF-8), Vim, metni genellikle dosya bozulmasına yol açan şekilde kodlamaya çalışır.

Bunu bir dosyayı açarak ve sadece kullanarak doğrulayabilirsiniz :w. Şimdi değişti.
Eğer ayarlarsanız LANGve LC_ALLkarşı C(ASCII), Vim şey dönüştürmez ve dosyalar aynı kalmak Vim herhangi baytlı kodlama yapmak gerekmez çünkü (hala olsa, bir yeni satır ekler).

Ben kişisel olarak ikiliyi de devre dışı bırakmayı tercih ediyorum set wrap, ancak diğerleri de etkinleştirmeyi tercih ediyor olabilir . YMMV. Yapılacak başka bir faydalı şey :set display=uhex. Kimden :help 'display':

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

Ve son bir ipucu olarak, cetveldeki imlecin altındaki karakterin onaltılık değerini %B( :set rulerformat=0x%B) ile gösterebilirsiniz .

Daha ileri: xxd

xxd(1)Bir dosyayı daha okunabilir bir biçime dönüştürmek için aracı kullanabilirsiniz ve (bu önemli bit), düzenlenen "okunabilir biçimi" ayrıştırıp ikili veri olarak geri yazabilirsiniz. xxdbir parçası vim, yani eğer vimyüklediyseniz de sahip olmalısınız xxd.

Kullanmak için:

$ xxd /bin/ls | vi -

Veya dosyayı daha önce açtıysanız, şunları kullanabilirsiniz:

:%!xxd

Şimdi değişikliklerinizi yapın, ekranın sol tarafındaki (onaltılık sayılar), sağ taraftaki değişikliklerin (yazdırılabilir gösterim) yazarken göz ardı edilmesini sağlamanız gerekir.

Kaydetmek için şunu kullanın xxd -r:

:%!xxd -r > new-ls

Bu dosyayı kaydedecektir new-ls.

Veya ikili dosyayı geçerli tamponda yüklemek için:

:%!xxd -r

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

Ve sonra sadece :wyazmak için kullanın . ( dikkat : binary yukarıdaki nedenlerle aynı sebeplerden dolayı, dosyaya yazmadan önce bu seçeneği belirlemek istiyorsunuz ).

Bunu kolaylaştırmak için tamamlayıcı tuşlar:

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

Bu ayrıca, 'Araçlar V HEX'e Dönüştür' ve 'Araçlar X Geri dönüştür' altında gVim kullanıyorsanız menüden de kullanılabilir.

Vim ipuçları wiki Daha fazla bilgi ve bazı yardımcı komut dosyaları ile bir sayfası vardır. Şahsen, muhtemelen bu ikili dosyaları düzenliyorsanız, gerçek bir hex editörü kullanarak daha iyi olduğunuzu düşünüyorum. Vim işi halledebilir , ancak belli ki bunun için tasarlanmamış ve :set binaryVim olmadan yazdığınızda ikili dosyalarınızı tahrip edebilir!


4
Güzel cevap, ama muhtemelen "Bunu evde denemeyin çocuklar!"
msn

Bazı baytları kaldırmam gerekirse ne olur? örneğin, ikili değerin ortasında.
Anton K

Vim'in ne yaptığını bilmiyorum, ama hiçbir şeyi değiştirmeme rağmen, 200 KB'lik bir ikili dosyaya 95KB metin ekliyor. İle bile :set binary noeol fenc=utf-8. Aslında dosyayı açmadan hemen önce yapıyor [noeol] [converted]. Neden vim tamponun% 150 daha büyük hale getirilmesi gerekiyor? Bunun gibi dosyaları bozmasını nasıl önlerim?
Braden Best

İşe yarayan tek şey okumak :r !xxd <file>(veya $ xxd <file> | vim -) okumak ve :w !xxd -r > <file>yazmaktır, ancak bu ideal değildir.
Braden Best

Mükemmel cevap Korusun URL'sinin çalışmadığını unutmayın; Bunu github.com/bwrsandman/Bless adresinde github'da buldum .
sonofagun

19

Bir ikili dosyanın içeriğini onaltılık görünümde görüntülemek için dosyayı açın, ikili modu açın ve arabellek xxdkomutunu kullanarak filtreleyin :

:set binary
:%!xxd

Sol alanda değişiklikler yapabilir (onaltılık sayıları düzenleyebilir) ve hazır olduğunuzda filtreleyebilir xxd -rve sonunda dosyayı kaydedebilirsiniz:

:%!xxd -r
:w

Açtıktan sonra ve kapanmadan önce filtreleme aşaması sıkıcı geliyorsa ve bunu sık sık .binuzantılı dosyalar ile yaparsanız, işlemi otomatik hale getirmek için bunu vimrc'nize ekleyebilirsiniz:

" 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

Ben bu talimatları izlerseniz (ikili dosyasını açın :%!xxd, :%!xxd -r, :wdaha sonra yazılı ikili dosyasıdır, hiç herhangi bir değişiklik!) Değil ... aslının aynıdır Bu durum sizin için (ı ile test mi /bin/ls). :set binaryKaydetmeden önce kullanmam gerekiyor (ayrıca nedenini açıklayan cevabımı da gör). Fakat ne olursa olsun, set binarygüvenlik için daima kullanırım ...
Martin Tournoij

1
Bunun yerine ekleyebilir augroupsenaryoyu ~/.vim/plugin/binary.vimsize yığılmayı istemiyorsanız.vimrc
thom_nic

Yabancı bir takma kullanıyorsanız, bu augroup Binaryliste 5.5'ten beri olan herhangi bir Vim'de :help hex-editingveya :help using-xxdiçinde bulunur (Eylül 1999).
bb010g

6

"Bvi" ​​editörünü kullanın. http://bvi.sourceforge.net/ (Her Linux deposunda.)

$ 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
Daha gelişmiş bir alternatif ise vim kontrollerine sahip olan bviplus.
Anton K,


3

TL; DR Cevap

Dosyayı Vim ile ikili modda açın:

vim -b <file_to_edit>

Vim'de, böyle altıgen düzenleme moduna geçin:

:%!xxd -p

Kaydetmek:

:%!xxd -p -r
:w

Bu, tamponu hex modundan geri dönüştürecek ve ardından dosyayı normal şekilde kaydedecektir.

-P seçeneğini not edin. Bu, tüm ekstra yazdırılabilir ve adres kabartmasını önler ve sadece altıgen sayısını gösterir. Ekstra bağlamı istiyorsanız, sadece -p atlayın.

Dosyayı Vim ile ikili modda açmamaya dikkat edin, kaydettiğinizde dosyanın sonuna bir (genellikle istenmeyen) LF karakteri ekleyecektir.


Bu gerçekten diğer cevaplarda olmayan hiçbir şey eklemiyor.
Herb Wolfe

5
Gerçek TL; DR :h using-xxdbu günden beri v7.0001ve muhtemelen daha uzun süredir var. Bu dokümanlar, insanlar dokümanı aradığında daha az aktif olur.
Tommy A

1

Bu , sizin için otomatik olarak ileri ve geri yazdığı geçici bir dosyayı kullanarak işi yapan kullanışlı bir küçük vim eklentisine benziyor.

Birkaç yıl önce kendi kullanımım için uyarladığım ve geliştirdiğim benzer bir eklenti buldum. Birisi isterse ilgili kodunu buraya yazdım. Aynı zamanda xxd aracını temel alır. Yukarıdan bağladığım GitHub sürümünün daha iyi çalıştığından eminim, ancak aslında kendim kullanmadım, bu yüzden emin olduğumu bildiğim bir yazı göndereceğimi düşündüm.

Bu diğer sürümün kaynağı, özellikle bu sayfa olan vim wikia idi .

İşte kod:

"-------------------------------------------------------------------------------  
" 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.