Bir Satır Beslemesi neden arama kaydının içinde Null karaktere ve komut satırında Satır Başı'na dönüştürülür?


12

Aşağıdaki metin varsa:

foo
bar

Görsel olarak seçiyorum ve kopyalıyorum.
Metin şimdi adlandırılmamış kayıtta saklanır "ve içeriği (çıktısı :reg "):

""   foo^Jbar^J

Bu grafiğe göre , ^Jbir Satır Beslemesi için düzeltme işareti olduğu anlaşılıyor .

Ben ayazarak kayıttaki adsız kayıt çoğaltmak istiyorsanız : :let @a = @"
İşte içeriği (çıktı :reg a):

"a   foo^Jbar^J

Değişmedi.

Şimdi yazarak arama kaydında çoğaltırsanız :let @/ = @", işte içeriği (çıktısı :reg /):

"/   foo^@bar^@

Önceki grafiğe göre, ^@Null karakter için işaret gösterimi gibi görünüyor .
Neden Satır Besleme otomatik olarak arama kaydının içinde Boş karaktere dönüştürülür (ancak akayıt değil )?

Adsız kaydı komut satırına (veya sonra bir arama içine /) eklersem :<C-R>", yazarak şunu eklersiniz:

:foo^Mbar^M

Yine, son grafiğe göre, ^Mbir Taşıt Dönüşü için caret gösterimi gibi görünüyor.
Bir Satır Beslemesi neden otomatik olarak komut satırında Satır Başı'na dönüştürülür?

Düzenle :

Genellikle aşağıdakileri yazarak bir gerçek kontrol karakteri ekleyebilirsiniz:
<C-V><C-{character in caret notation}>

Örneğin, <C-R>yazarak bir değişmez değer ekleyebilirsiniz <C-V><C-R>.
Görünüşe göre herhangi bir kontrol karakteri için yapabilirsiniz.
Ancak ben bir arabellek içine veya komut satırına değişmez bir LF ekleyemediğimi fark ettim, çünkü ben yazarsanız: <C-V><C-J>ekler ^@, yerine boş bir karakter ekler ^J.
Aynı nedenden ötürü bir LF, arama yazmacı içinde NUL değerine dönüştürülür mü?

Düzenleme 2 :

İçinde :h key-notation, bunu okuyabiliriz:

<Nul>       zero            CTRL-@    0 (stored as 10) <Nul>
<NL>        linefeed        CTRL-J   10 (used for <Nul>)

stored as 10İlk satırda ve bölüm used for <Nul>ikinci satırda bir LF ve NUL arasındaki örtüşme çeşit var olduğunu gösterebilir ve aynı şey olarak yorumlanabilir. Sonra önceki komutu yürütülürken, çünkü Ama, aynı şey olamaz :let @/ = @"ben yazarsanız, n2 hatlarının sonraki geçtiği almak için normal modda foove baryerine olumlu maçı alma, aşağıdaki hata mesajım var:

E486: Pattern not found: foo^@bar^@

Bu bağlantının yanı sıra , bir NUL değerinin bir dizenin sonunu, LF ise bir metin dosyasındaki satırın sonunu ifade ettiğini açıklamaktadır.

Ve bir NUL stored as 10yardımın söylediği gibi, bir LF ile aynı kod ise, Vim 2 arasındaki farkı nasıl oluşturabilir?

Düzenleme 3 :

Belki bir LF ve bir NUL 10yardımda belirtildiği gibi aynı ondalık kodla kodlanmıştır . Ve Vim bağlam sayesinde 2 arasındaki farkı yaratıyor. Ondalık kodu 10arabellekte veya herhangi bir kayıtta bulunan, arama ve komut kayıtları dışında bir karakterle karşılaşırsa, karakteri LF olarak yorumlar.
Ancak arama kaydında ( :reg /) onu bir NUL olarak yorumlar, çünkü bir arama bağlamında Vim, yalnızca bir kavramın end of line in a filemantıklı olmadığı bir dizeyi arar, çünkü bir dize bir dosya değildir ( atomu \naranan bir desende kullanmaya devam ediyor , ama belki de bu normal ifade motorunun sadece bir özelliği?). Böylece otomatik 10olarak bir NUL olarak yorumlanır çünkü en yakın kavramdır ( end of stringend of line).

Aynı şekilde, komut satırı / komut registerında ( :reg :) kodu 10CR olarak yorumlar , çünkü burada kavramı end of line in a filemantıklı değildir. En yakın kavramdır end of commandVim yorumladığını böylece 10vurma, çünkü bir CR olarak Enterbir komut çalıştırmak / sona yoludur ve CR isabet aynıdır Enterolduğunda sizi bir edebi biri insert beri <C-V><Enter>, ^Mgörüntülenir.

Belki de kodu olan karakterin 10bağlama göre değişmesi:

  • arabellekte satır sonu ( ^J)
  • aramadaki dizenin sonu ( ^@)
  • komut satırında komutun sonu ( ^M)

2
Bazen beklenmedik NULL karakterlerin ortaya çıkması , dizeleri işleyen temel C işlevinden kaynaklanır. Bu C dizeleri nasıl işlediğini açıklaması sen bağlantılı olduğu dahili C dizelerle sınırlayan açıklıyor NULL. NULLmetinlerde nadiren bu amaç için iyi bir karakter olmasını sağlar. Bunun bir sonucu olarak, C programı (vim) dahili bir C fonksiyonuna "boş" bir dizge
geçirmeye çalıştıysa

2
örneğin someFunction(arg1, "")arg 2 "" yani "tam anlamıyla hiçbir şey olmayan tırnaklar arasındaki öğe - bir" boş ". NULL görünebilir, çünkü" dize sınırlandı gibi temel C uygulaması tarafından eklenmiştir ". bunu nasıl kontrol edeceğinizi - ancak olası bir neden olarak akla geliyor.
the_velour_fog

1
Ayrıca konusundaki tartışmaya \rve \nfarklılığa bakın:substitute .
jamessan

Yanıtlar:


5

İlk olarak, bu çok kapsamlı ve düşünceli gönderi için teşekkür ederim.

Bazı testlerden sonra şu sonuca vardım:

  1. : Kontrol karakterleri şapka gösterimi kullanılarak görüntülenir ^Miçin <CR>(satırbaşı) ve ^Jiçin <LF>(hat besleme). Tamponlarda, <EOL>(satır sonu) yeni ekran satırları olarak görüntülenir ve enter tuşuyla girilir. <EOL>tampon dosya formatına bağlıdır: <EOL> = <CR>|<LF>|<CR><LF>için mac|unix|dossırasıyla.

  2. Bir arabelleği düzenlerken, dosya biçimi her zaman ayarlanır. Açılmış bir arabellek dosya biçimini değiştirmek için aşağıdaki dönüştürmeyi kullanabilirsiniz <EOL>:

    :set f[ile]f[ormat]=mac|unix|dos
    

    Dönüştürme ek olarak <EOL>, bu komut dönüştürür <LF>için <CR>gelen dosya biçimini değiştirirken maciçin unix|dos, tersine, ve <CR>hiç <LF>dosya biçimini değiştirirken unix|dosiçin mac. Arabelleğin gerçek baytlarını görmek için, uygun onaltılık düzenleyici xxd'yi kullanarak arabelleğin metinsel temsilini onaltılı gösterimine dönüştüren aşağıdaki komutu kullanabilirsiniz:

    :%!xxd
    
  3. (Komutuyla gösterdi kayıtlar olarak :reg[isters]veya :di[splay]), <EOL>her zaman vardır görüntülenen olarak ^J(ama hepsi değil ^Jşunlardır <EOL>bakılmaksızın tampon dosya biçiminin,). Ancak <EOL>edilir saklı olması gerektiği gibi. Kayıtlarda görsel olarak gerçek ^J(yani <LF>) diğerlerinden ^J(yani ) ayırt edebilmek için <EOL>, kontrol karakterlerinin düzeltme işareti yerine onaltılık değerleri görüntüleyen aşağıdaki komutu kullanabilirsiniz <EOL>:

    :set d[ispla]y=uhex
    
  4. Arama düzenlerinde ve ikame dizelerinde:

    \r = newline different from <EOL> (<CR> if <EOL> = <CR><LF>|<LF>, <LF> if <EOL> = <CR>)
    \n = <EOL>
    
  5. Her yerde:

    <C-V><C-M>|<C-V><EOL> = newline different from <EOL>
    <C-V><C-J> = <NUL>
    

    Dosya biçimi olduğunda bu gösterileri o dos, bu girişe imkansızdır <LF>çünkü, <EOL> = <CR><LF>ve <C-V><C-M>|<C-V><EOL> = <CR>.

  6. İkame dizelerinde:

    • farklı yeni satır <EOL>edilir yorumlanır olarak <EOL>;

    • <EOL>olan yorumlanmış olarak <NUL>.

    Bu yüzden, 4. göre, :%s[ubstitute]/\r/\r/gher satır diğerlerinden farkı yerine <EOL>içeren tampon içinde <EOL>iken, :%s[ubstitute]/\n/\n/gyerine geçer, her <EOL>tamponda <NUL>.

  7. Arama kaydı olarak /ve komut kayıt :, <EOL>olan dönüştürülmüş için

    • yeni satır veya sırasıyla <EOL>bir kayıttan eklendikten farklı ;/<C-R>{register}:<C-R>{register}

    • <NUL>Bir kayıt ile takıldığında :let @/=@{register}veya :let @:=@{register}sırasıyla.

  8. Tamponlar olarak, gelen satır farklı <EOL>olan dönüştürülmüş için <EOL>kullanan bir abone kütüğünden takıldığında i<C-R>{register}.

Bir Satır Beslemesi neden arama kaydının içinde Null karaktere ve komut satırında Satır Başı'na dönüştürülür?

Kopyalamadan önce <LF>isimsiz kasadan "diğer kayıtlar ile, girmek gerekir <LF>ve kayıt içine koyun ". Dosya biçimi böyleyse unix, bunu yyboş bir satıra kullanarak yapabilirsiniz ; dosya biçimi ise macbunu kullanarak yapabilirsiniz i<C-V><C-M><Esc>yl; dosya biçimi ise dos, giremezsiniz <LF>(çapraz başvuru 5.).

Şimdi ifadeniz kısmen yanlış, çünkü

  • Eğer kopyalama aynı yöntemi kullanmayan <LF>kasadan "arama kayıt içine /ve komut kayıt :. Sen kullanmak :let @/=@"kayıt içine kopyalamak için /ve :<C-R>"kayıt içine kopyalamak için :. Her iki durumda da sırasıyla /<C-R>"ve kullanmanız :<C-R>"aynı sonucu verir ( <CR>);

  • <LF>iki farklı kopyalama yönteminizle gerçekleşen dönüşümler yalnızca dosya biçimi olduğunda gerçekleşir unix. Eğer durum bu ise mac, <LF>bir değil kaydına kopyalanan zaman dönüştürülebilir /veya kayıt :ve eğer doshatta giriş yapamazsınız <LF>.

Doğru ifade 7'de verilmiştir. Ama bunun nedenlerini gerçekten bilmiyorum.


Bunu anlamak neden bu kadar zor ... SO ve vim-SE ve vim yardımı üzerine birkaç yazı araştırdım, ancak tamamen tutarlı ve hala karışık değil.
Violapterin
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.