Если у меня есть следующий текст:
foo
bar
Я визуально выбираю и копирую.
Текст теперь хранится в безымянном регистре, "
и вот его содержимое (вывод :reg "
):
"" foo^Jbar^J
В соответствии с этим графиком , кажется, что ^J
это обозначение каретки для перевода строки.
Если я хочу дублировать безымянный регистр в a
регистре, набрав: :let @a = @"
Вот его содержимое (вывод :reg a
):
"a foo^Jbar^J
Это не изменилось.
Если я теперь продублирую его в регистре поиска, набрав :let @/ = @"
, вот его содержимое (вывод :reg /
):
"/ foo^@bar^@
Согласно предыдущему графику, это похоже ^@
на символ каретки для нулевого символа.
Почему перевод строки автоматически преобразуется в нулевой символ в регистре поиска (но не в a
регистре)?
Если я вставляю безымянный регистр в командной строке (или в поиске после /
), набрав :<C-R>"
, вот что вставлено:
:foo^Mbar^M
Опять же, в соответствии с последним графиком, ^M
похоже, каретная нотация для возврата каретки.
Почему перевод строки автоматически преобразуется в возврат каретки в командной строке?
Редактировать :
Обычно вы можете вставить буквенный управляющий символ, набрав:
<C-V><C-{character in caret notation}>
Например, вы можете вставить в буквальном смысле <C-R>
, набрав <C-V><C-R>
.
Вы можете сделать это для, казалось бы, любого управляющего персонажа.
Однако я заметил, что я не могу вставить буквальный LF внутри буфера или в командной строке, потому что, если я наберу: <C-V><C-J>
он вставляет ^@
нулевой символ вместо ^J
.
По той же причине LF преобразуется в NUL внутри регистра поиска?
Изменить 2 :
В :h key-notation
, мы можем прочитать это:
<Nul> zero CTRL-@ 0 (stored as 10) <Nul>
<NL> linefeed CTRL-J 10 (used for <Nul>)
stored as 10
Часть на первой линии и used for <Nul>
на второй линии может свидетельствовать о том , что есть какая - то перекрытия между LF и NUL, и что они могут быть интерпретированы как то же самое. Но они не могут быть одинаковыми, потому что после выполнения предыдущей команды :let @/ = @"
, если я набираю текст n
в обычном режиме, чтобы перейти к следующему вхождению из 2 строк, foo
и bar
вместо получения положительного совпадения у меня появляется следующее сообщение об ошибке:
E486: Pattern not found: foo^@bar^@
Кроме того, эта ссылка, кажется, объясняет, что NUL обозначает конец строки, тогда как LF обозначает конец строки в текстовом файле.
И если NUL, stored as 10
как говорится в справке, это тот же код, что и для LF, как Vim может сделать разницу между двумя?
Изменить 3 :
Возможно, LF и NUL кодируются с одним и тем же десятичным кодом 10
, как говорится в справке. И Vim делает разницу между двумя благодаря контексту. Если он встречает символ, десятичный код которого находится 10
в буфере или любом регистре, кроме регистров поиска и команд, он интерпретирует его как LF.
Но в search register ( :reg /
) он интерпретирует его как NUL, потому что в контексте поиска Vim ищет только строку, в которой концепция end of line in a file
не имеет смысла, потому что строка не является файлом (что странно, поскольку вы можете по-прежнему использовать атом \n
в искомом шаблоне, но, возможно, это только особенность движка регулярных выражений?). Таким образом, он автоматически интерпретируется 10
как NUL, потому что это ближайшая концепция ( end of string
≈ end of line
).
И точно так же в командной строке / command register ( :reg :
) он интерпретирует код 10
как CR, потому что концепция end of line in a file
здесь не имеет смысла. Ближайшая концепция end of command
так Vim толкует 10
как CR, так как ударять Enter
путь до конца / выполнить команду и CR такой же , как удары Enter
, так как при вставке буквального с <C-V><Enter>
, ^M
отображаются.
Может быть, интерпретация символа, чей код 10
меняется в зависимости от контекста:
- конец строки в буфере (
^J
) - конец строки в поиске (
^@
) - конец команды в командной строке (
^M
)
источник
NULL
символов вызвано базовой функцией C, которая обрабатывает строки. Это объяснение того, как C обрабатывает строки, с которыми вы связались, объясняет, что внутренне C разделяет строки с помощьюNULL
.NULL
в тексте встречаются достаточно редко, что делает его хорошим персонажем для этой цели. Следствием этого является то, что если программа C (vim) пыталась передать «пустую» строку во внутреннюю функцию CsomeFunction(arg1, "")
где arg 2 было,""
т. е. «элемент между кавычками, который буквально ничто -« пустой ». Может быть NULL, потому что он был« добавлен »базовой реализацией C, поскольку он ограничил строку. Я не знаю как бы вы проверили это - но это приходит на ум в качестве возможной причины\r
и\n
разницу в:substitute
.Ответы:
Во-первых, спасибо за этот очень полный и вдумчивый пост.
После некоторых испытаний я пришел к такому выводу:
Управляющие символы отображаются с использованием обозначения каретки:
^M
для<CR>
(возврат каретки) и^J
для<LF>
(перевод строки). В буферах<EOL>
(конец строки) отображаются как новые строки экрана и вводятся клавишей ввода.<EOL>
зависит от формата файла буфера:<EOL> = <CR>|<LF>|<CR><LF>
дляmac|unix|dos
соответственно.При редактировании буфера формат файла всегда устанавливается. Чтобы изменить формат файла открытого буфера, вы можете использовать следующую команду, которая преобразует
<EOL>
:Кроме преобразования
<EOL>
, эта команда преобразует<LF>
в<CR>
при изменении формата файла отmac
доunix|dos
, и наоборот,<CR>
чтобы<LF>
при изменении формата файла отunix|dos
кmac
. Чтобы увидеть реальные байты буфера, вы можете использовать следующую команду, которая преобразует текстовое представление буфера в его шестнадцатеричное представление, используя удобный шестнадцатеричный редактор xxd:В регистрах (показавших с командой
:reg[isters]
или:di[splay]
)<EOL>
всегда отображаются в виде^J
(но не все^J
это<EOL>
), независимо от формата файла буфера. Однако<EOL>
будут сохранены , как они должны. Чтобы иметь возможность отличать визуально реальные^J
(то есть<LF>
) от других^J
(то есть<EOL>
) в регистрах, вы можете использовать следующую команду, которая отображает шестнадцатеричные значения вместо обозначения каретки контрольных символов, отличного от<EOL>
:В шаблонах поиска и строках подстановки:
Где угодно:
Это показывает, что при формате файла
dos
ввод невозможен<LF>
, так как<EOL> = <CR><LF>
и<C-V><C-M>|<C-V><EOL> = <CR>
.В строках подстановки:
новая строка отличается от
<EOL>
будут интерпретироваться , как<EOL>
;<EOL>
которые интерпретируются , как<NUL>
.Таким образом, согласно 4.,
:%s[ubstitute]/\r/\r/g
заменяет каждую новую строку, отличную от<EOL>
в буфере<EOL>
, в то время как:%s[ubstitute]/\n/\n/g
заменяет каждую<EOL>
в буфере с<NUL>
.В поле поиска регистр
/
и регистр команд:
,<EOL>
которые преобразуются вновая строка отличается от
<EOL>
вставленной из регистра с/<C-R>{register}
или:<C-R>{register}
соответственно;<NUL>
при вставке из регистра с:let @/=@{register}
или:let @:=@{register}
соответственно.В буферах, отличается от перевода строки
<EOL>
будут преобразованы , чтобы<EOL>
при вставке из регистра , используяi<C-R>{register}
.Перед копированием
<LF>
из безымянного регистра"
в другие регистры, вам необходимо ввести<LF>
и внести его в регистр"
. Если формат файлаunix
, вы можете сделать это, используяyy
пустую строку; если формат файлаmac
, вы можете сделать это с помощьюi<C-V><C-M><Esc>yl
; если формат файлаdos
, вы не можете ввести<LF>
(см. 5.).Теперь ваше утверждение частично неверно, так как
Вы не используете один и тот же метод для копирования
<LF>
из регистра"
в регистр поиска и регистр/
команд:
. Вы используете:let @/=@"
для копирования в реестр/
и:<C-R>"
для копирования в реестр:
. Использование/<C-R>"
и:<C-R>"
соответственно даст вам одинаковый результат (<CR>
) в обоих случаях;преобразования,
<LF>
которые происходят с вашими двумя различными методами копирования, происходят только тогда, когда формат файлаunix
. Еслиmac
,<LF>
это не конвертируются при копировании в реестре/
или реестре:
, и еслиdos
вы не можете даже вход<LF>
.Правильное утверждение дает 7. Но я действительно не знаю причин этого.
источник