Jeśli mam następujący tekst:
foo
bar
Wybieram go wizualnie i kopiuję.
Tekst jest teraz przechowywany w rejestrze bez nazwy "
i oto jego zawartość (wynik :reg "
):
"" foo^Jbar^J
Zgodnie z tym wykresem wydaje się, że ^J
jest to notacja karetki dla przesuwania linii.
Jeśli chcę powielić rejestr nienazwany w a
rejestrze, wpisując: :let @a = @"
Oto jego zawartość (wynik :reg a
):
"a foo^Jbar^J
Nie zmieniło się.
Jeśli teraz powielę go w rejestrze wyszukiwania, wpisując :let @/ = @"
, oto jego zawartość (wynik :reg /
):
"/ foo^@bar^@
Zgodnie z poprzednim wykresem wydaje się, że ^@
jest to znak karetki dla znaku Null.
Dlaczego wysuw wiersza jest automatycznie konwertowany na znak Null w rejestrze wyszukiwania (ale nie w a
rejestrze)?
Jeśli wstawię nienazwany rejestr w wierszu polecenia (lub w środku wyszukiwania po /
), wpisując :<C-R>"
, oto co jest wstawiane:
:foo^Mbar^M
Ponownie, zgodnie z ostatnią tabelą, ^M
wydaje się być notacją karetki zwrotu powozu.
Dlaczego wiersz wiersza jest automatycznie przekształcany w wiersz powrotu karetki w wierszu polecenia?
Edytuj :
Zwykle można wstawić dosłowny znak kontrolny, wpisując:
<C-V><C-{character in caret notation}>
Na przykład możesz wstawić literał <C-R>
, pisząc <C-V><C-R>
.
Możesz to zrobić dla pozornie dowolnej postaci kontrolnej.
Zauważyłem jednak, że nie jestem w stanie wstawić dosłownego pliku LF do bufora lub wiersza poleceń, ponieważ jeśli napiszę: <C-V><C-J>
wstawi ^@
, zamiast znaku null ^J
.
Czy z tego samego powodu LF jest konwertowany na NUL w rejestrze wyszukiwania?
Edycja 2 :
W :h key-notation
możemy przeczytać to:
<Nul> zero CTRL-@ 0 (stored as 10) <Nul>
<NL> linefeed CTRL-J 10 (used for <Nul>)
stored as 10
Część na pierwszej linii, a used for <Nul>
na drugiej linii może wskazywać, że istnieje jakiś rodzaj zachodzenia między LF i NUL, i że mogą być interpretowane jako samo. Ale nie mogą być tym samym, ponieważ po wykonaniu poprzedniego polecenia :let @/ = @"
, jeśli piszę n
w trybie normalnym, aby przejść do następnego wystąpienia 2 linii foo
i bar
zamiast uzyskania pozytywnego dopasowania, pojawia się następujący komunikat o błędzie:
E486: Pattern not found: foo^@bar^@
Poza tym ten link wydaje się wyjaśniać, że NUL oznacza koniec łańcucha, podczas gdy LF oznacza koniec linii w pliku tekstowym.
A jeśli NUL jest, stored as 10
jak mówi pomoc, czyli taki sam kod jak dla LF, w jaki sposób Vim może rozróżnić 2?
Edycja 3 :
Być może LF i NUL są kodowane tym samym kodem dziesiętnym 10
, jak mówi pomoc. A Vim robi różnicę między tymi 2 dzięki kontekstowi. Jeśli napotka znak, którego kod dziesiętny znajduje się 10
w buforze lub dowolnym rejestrze, z wyjątkiem rejestrów wyszukiwania i poleceń, interpretuje go jako LF.
Ale w rejestrze wyszukiwania ( :reg /
) interpretuje to jako NUL, ponieważ w kontekście wyszukiwania Vim szuka tylko ciągu znaków, w którym koncepcja end of line in a file
nie ma sensu, ponieważ ciąg nie jest plikiem (co jest dziwne, ponieważ można nadal używasz atomu \n
w szukanym wzorze, ale może to tylko funkcja silnika wyrażeń regularnych?). Więc automatycznie interpretuje 10
jako NUL, ponieważ jest to najbliższa koncepcja ( end of string
≈ end of line
).
I w ten sam sposób, w wierszu poleceń / register register ( :reg :
) interpretuje kod 10
jako CR, ponieważ pojęcie end of line in a file
tutaj nie ma sensu. Najbliższa koncepcja jest end of command
taka, że Vim interpretuje 10
jako CR, ponieważ uderzanie Enter
jest sposobem na zakończenie / wykonanie polecenia, a CR jest tym samym co uderzanie Enter
, ponieważ po wstawieniu dosłownego za pomocą <C-V><Enter>
, ^M
wyświetla się.
Może interpretacja znaku, którego kod 10
zmienia się zgodnie z kontekstem:
- koniec linii w buforze (
^J
) - koniec ciągu w wyszukiwaniu (
^@
) - koniec polecenia w wierszu polecenia (
^M
)
źródło
NULL
znaków jest spowodowane podstawową funkcją C, która obsługuje ciągi znaków. To objaśnienie, w jaki sposób C przetwarza ciągi, które łączysz, wyjaśnia, że wewnętrznie C rozgranicza ciągi za pomocąNULL
.NULL
s występują w tekście rzadko, co sprawia, że jest to dobry znak do tego celu. Konsekwencją tego jest to, że jeśli program C (vim) próbował przekazać „pusty” ciąg do wewnętrznej funkcji CsomeFunction(arg1, "")
gdzie arg 2 to""
np. „pozycja między cudzysłowami, która jest dosłownie niczym -„ pusta ”. Może pojawić się wartość NULL, ponieważ została„ dodana ”przez podstawową implementację języka C, ponieważ rozgraniczała ciąg. Nie wiem jak byś to sprawdził - ale wydaje się, że to możliwa przyczyna.\r
i\n
różnice w:substitute
.Odpowiedzi:
Po pierwsze, dziękuję za ten bardzo obszerny i przemyślany post.
Po kilku testach doszedłem do tego wniosku:
Znaki kontrolne są wyświetlane za pomocą notacji karetki:
^M
dla<CR>
(powrót karetki) i^J
dla<LF>
(przesunięcie wiersza). W buforach<EOL>
(koniec linii) są wyświetlane jako nowe linie ekranu i są wprowadzane za pomocą klawisza Enter.<EOL>
zależy od formatu pliku bufora:<EOL> = <CR>|<LF>|<CR><LF>
dlamac|unix|dos
odpowiednio.Podczas edycji bufora format pliku jest zawsze ustawiony. Aby zmienić format pliku otwartego bufora, możesz użyć następującego polecenia, które konwertuje
<EOL>
:Oprócz konwertowania
<EOL>
to polecenie konwertuje<LF>
na<CR>
przy zmianie formatu pliku zmac
naunix|dos
i odwrotnie<CR>
na<LF>
przy zmianie formatu pliku zunix|dos
namac
. Aby zobaczyć rzeczywiste bajty bufora, możesz użyć następującego polecenia, które przekształca tekstową reprezentację bufora na jego reprezentację szesnastkową za pomocą wygodnego edytora szesnastkowego xxd:W rejestrach (wykazali za pomocą polecenia
:reg[isters]
lub:di[splay]
)<EOL>
zawsze są wyświetlane jako^J
(ale nie wszystkie^J
są<EOL>
), niezależnie od formatu pliku bufora. Jednak<EOL>
są przechowywane tak, jak powinny. Aby móc odróżnić wizualnie rzeczywiste^J
(tj.<LF>
) Od innych^J
(tj.<EOL>
) W rejestrach, możesz użyć następującego polecenia, które wyświetla wartości szesnastkowe zamiast notacji znakowej znaków kontrolnych innych niż<EOL>
:W wzorach wyszukiwania i ciągach podstawień:
Wszędzie:
To pokazuje, że gdy format pliku
dos
jest niemożliwy, nie można go wprowadzić<LF>
, ponieważ<EOL> = <CR><LF>
i<C-V><C-M>|<C-V><EOL> = <CR>
.W ciągach podstawienia:
nowa linia inna niż
<EOL>
są interpretowane jako<EOL>
;<EOL>
są interpretowane jako<NUL>
.Tak więc, zgodnie z 4.,
:%s[ubstitute]/\r/\r/g
zamienia każdą nową<EOL>
linię inną niż w buforze na<EOL>
, a:%s[ubstitute]/\n/\n/g
zastępuje każdą<EOL>
w buforze na<NUL>
.W poszukiwaniu rejestru
/
ewidencji i poleceń:
,<EOL>
są konwertowane donowa linia różni się od
<EOL>
po wstawieniu z rejestru z/<C-R>{register}
lub:<C-R>{register}
odpowiednio;<NUL>
po wstawieniu z rejestru za pomocą:let @/=@{register}
lub:let @:=@{register}
odpowiednio.W buforach nowa linia inna niż
<EOL>
jest konwertowana na<EOL>
po wstawieniu z rejestru za pomocąi<C-R>{register}
.Przed skopiowaniem
<LF>
z nienazwanego rejestru"
do innych rejestrów, musisz wprowadzić<LF>
i umieścić go w rejestrze"
. Jeśli format pliku tounix
, możesz to zrobić, używającyy
pustej linii; jeśli format pliku tomac
, możesz to zrobić za pomocąi<C-V><C-M><Esc>yl
; jeśli format pliku todos
, nie można wprowadzić danych<LF>
(porównaj 5.).Teraz twoje stwierdzenie jest częściowo błędne
nie używasz tej samej metody do kopiowania
<LF>
z rejestru"
do rejestru wyszukiwania/
i rejestru poleceń:
. Używasz:let @/=@"
do kopiowania do rejestru/
i:<C-R>"
do kopiowania do rejestru:
. Użycie/<C-R>"
i:<C-R>"
odpowiednio da ci ten sam wynik (<CR>
) w obu przypadkach;konwersje,
<LF>
które odbywają się za pomocą dwóch różnych metod kopiowania, zachodzą tylko wtedy, gdy format pliku jestunix
. Jeśli takmac
, nie<LF>
jest konwertowany po skopiowaniu do rejestru lub rejestru , a jeśli tak , nie można nawet wprowadzić danych ./
:
dos
<LF>
Właściwe stwierdzenie podaje 7. Ale tak naprawdę nie znam powodów.
źródło