Как заменить символ новой строкой в ​​Vim

1967

Я пытаюсь заменить каждый ,в текущем файле новой строкой:

:%s/,/\n/g 

Но он вставляет то, что выглядит как ^@вместо новой строки. Файл не в режиме DOS или что-то еще.

Что мне делать?

Если вам любопытно, как и мне, проверьте вопрос: почему \ V newline для Vim? также.

Винко Врсалович
источник
2
Stack Overflow - сайт для вопросов программирования и разработки. Этот вопрос кажется не по теме, потому что он не касается программирования или разработки. Смотрите, какие темы я могу задать здесь, в Справочном центре. Возможно, лучше спросить Super User или Unix & Linux Stack Exchange .
1818 года
5
@jww этому вопросу 10 лет ... кажется, слишком стар, чтобы мигрировать. Есть много подобных вопросов, например: stackoverflow.com/questions/10175812/…
Винко Врсалович
14
@jww vim - это инструмент, обычно используемый для программистов, а вопросы об инструментах, обычно используемых для программистов, находятся в теме переполнения стека . Хотя, очевидно, это больше подходит для Vi и Vim .
user202729

Ответы:

2565

Используйте \rвместо \n.

Подстановка путем \nвставки нулевого символа в текст. Чтобы получить новую строку, используйте \r. Однако при поиске новой строки вы все равно используете \n. Эта асимметрия обусловлена ​​тем, что \nи \r делают немного разные вещи :

\nсоответствует концу строки (перевод строки), тогда как \rсоответствует возврату каретки. С другой стороны, в подстановках \nвставляется нулевой символ, в то время как \rвставляется символ новой строки (точнее, он обрабатывается как ввод <CR>). Вот небольшой, неинтерактивный пример, чтобы проиллюстрировать это, используя функцию командной строки Vim (другими словами, вы можете скопировать и вставить следующее в терминал, чтобы запустить его). xxdпоказывает hexdump полученного файла.

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a                                bar.
After:
0000000: 000a 720a                                ..r.

Другими словами, \nвставил байт 0x00 в текст; \rвставил байт 0x0a.

Конрад Рудольф
источник
127
/ r рассматривается как нажатие клавиши Enter / Return. Работает на всех платформах.
Лука Маринко
73
Смотрите также Почему \ ra newline для Vim? ,
Эндрю Маршалл
14
Я хотел бы, чтобы это работало для классического vi. В AIX v6.1 \rне работает так Но вы можете нажать Ctrl-V Enterвместо ввода \r, и это работает.
eksortso
3
Я опоздал на вечеринку. Если \rвставляет <CR>и \nвставляет ноль, как бы я заменить что-то с возвратом каретки?
Мистер Лама
2
@SunnyRaj ты уверен в истории CR и LF? У меня сложилось впечатление, что первоначально LF перемещал бумагу на один ряд вперед, но не двигал печатающую головку, а CR перемещал печатающую головку, но не перемещал бумагу. В результате, если ваша ОС не конвертировала ввод перед печатью, вы не могли просто использовать только LF или CR для получения правильного вывода. MS DOS использовала необработанные данные принтера в качестве формата текстового файла, Mac OS использовала CR и преобразовала их в исходный формат принтера, а UNIX использовала LF и преобразовала их в исходный формат принтера.
Микко Ранталайнен
210

Вот хитрость:

Во-первых, установите сеанс Vi (m), чтобы разрешить сопоставление с шаблоном со специальными символами (например, символом новой строки). Вероятно, стоит поместить эту строку в ваш файл .vimrc или .exrc:

:set magic

Затем сделайте:

:s/,/,^M/g

Чтобы получить ^Mперсонажа, наберите Ctrl+ Vи нажмите Enter. В операционной системе Windows, сделайте Ctrl+ Q, Enter. Единственный способ запомнить это, помня, как мало они имеют смысла:

A: Какой худший контрольный символ использовать для представления новой строки?

B: Либо q(потому что это обычно означает «Выход»), либо vпотому, что было бы так легко набрать Ctrl+ Cпо ошибке и убить редактор.

A: Сделайте это так.

логан
источник
9
Я использую GVim на Windows, и мне не нужно ни :set magic(это не в моем ~ / _vimrc либо), ни ctrl-q. Простое, ctrl-vза которым следует ввод, создает ^Mдля меня характер.
Крис Филлипс
5
Cv не представляет новую строку; это команда «бежать от следующего буквального символа». Я не знаю, что Cv является мнемоникой для обоих, но есть причина, по которой он мысленно не отображается на новую строку.
Джим Стюарт
27
Ctrl-v является мнемоникой для "дословно" - то есть экранирование следующей клавиши, нажатой до ее "дословно" кода клавиши / символа. В Windows это вставить: чтобы все было знакомо. Ctrl-Q для "(не) Цитировать" может быть. В любом случае, довольно глупо - но вы можете использовать его в двоичных файлах - например, для поиска от Ctrl-A до Ctrl-Z (Ascii 1-26, я думаю).
Томаш Гандор
1
Ctrl-Cна самом деле не убивает редактор, хотя он может отменить вас обратно в обычный режим. Ctrl-Vозначает дословно и Ctrl-Qозначает, что кто-то допустил ошибку при загрузке $VIMRUNTIME/mswin.vimфайла конфигурации. Тебе не нужен Мсвин. Просто используйте вместо этого свой собственный vimrc.
00день
вау ---- это удивительно Я делал sed -n l до сих пор. Приятно знать, что того же можно достичь с помощью Ctrl-vvim.
Арпит
98

В синтаксисе s/foo/bar, \rи \nимеют разные значения в зависимости от контекста.


Короткий:

Для foo:

\ n = перевод строки (LF в Linux / Mac, CR + LF в Windows)
\ r = возврат каретки (CR)

Для bar:

\ r = перевод строки
\ n = нулевой байт.

Длиннее (с номерами ASCII):

NUL= 0x00 = 0 = Ctrl+ @
LF= 0x0A = 10 = Ctrl+ J
CR= 0x0D = 13 = Ctrl+M

Вот список управляющих символов ASCII . Вставьте их в Vim через Ctrl+ V, Ctrl+ ---key---.

В Bash или других оболочках Unix / Linux просто введите Ctrl+ ---key---.

Попробуйте Ctrl+ Mв Bash. Это то же самое, что и удар Enter, поскольку оболочка понимает, что имеется в виду, хотя системы Linux используют перевод строки для разграничения строк.

Для вставки литералов в bash, добавление их к Ctrl+ Vтакже будет работать.

Попробуй в Bash:

echo ^[[33;1mcolored.^[[0mnot colored.

Это использует escape-последовательности ANSI . Вставьте два ^[«S с помощью Ctrl+ V, Esc.

Вы также можете попробовать Ctrl+ V, Ctrl+ M, Enter, что даст вам:

bash: $'\r': command not found

Помните \rсверху? :>

Этот список управляющих символов ASCII отличается от полной таблицы символов ASCII тем , что там Ctrlможно найти управляющие символы, которые вставляются в консоль / псевдотерминал / Vim с помощью ключа (ха-ха).

В то время как в C и большинстве других языков вы обычно используете восьмеричные коды для представления этих «символов».

Если вы действительно хотите знать, откуда все это: TTY демистифицировано . Это лучшая ссылка, с которой вы столкнетесь по этой теме, но будьте осторожны: там будут драконы.


TL; DR

Обычно foo= \nи bar= \r.

sjas
источник
1
Так что я заинтригован, как бы вы заменили персонажа на возврат каретки
кодовый снимок
2
@codeshot :s/x/^M/gдолжен сделать. Вставьте ^Mпереход, ctrl-vа затем ctrl-m.
Sjas
3
Спасибо sjas, вы знаете, этот вопрос является одним из самых странных за все время. 1008 голосов за ответ, который в основном говорит не более, чем «vim делает то, что вы нашли. Это потому, что vim делает то, что вы нашли. Никогда не забывайте, что vim делает то, что вы нашли». Я надеялся найти короткий список кодов для интересных символов в шаблоне, замену и причину странности, чтобы ее было легко запомнить и предсказать другие подобные странности. Это получило бы мой голос.
кодовый снимок
@codeshot вам может помочь список управляющих символов ascii. См. Cs.tut.fi/~jkorpela/chars/c0.html для дальнейшего использования. Я обновлю свой ответ, чтобы включить две ссылки.
sjas
55

Вам необходимо использовать:

:%s/,/^M/g

Чтобы получить ^Mсимвол, нажмите Ctrl+, vа затем Enter.

кендырь
источник
4
Я должен сделать <Cv> <Cm>, чтобы получить символ ^ M.
Джезен Томас
39

\r может сделать работу здесь для вас.

Лазар
источник
24

С Vim на Windows используйте Ctrl+ Qвместо Ctrl+ V.

grantc
источник
16

Это лучший ответ на мой взгляд, но в таблице это было бы лучше:

Почему \ ra newline для Vim?

Итак, формулировка:

Вы должны использовать, \rчтобы использовать перевод строки (ASCII 0x0A, новая строка Unix) в замене регулярных выражений, но это характерно для замены - обычно вы должны продолжать использовать \nдля перевода строки и \rвозврата каретки.

Это потому, что Vim используется \nв качестве замены для обозначения символа NIL (ASCII 0x00). Возможно, вы ожидали, что \0вместо этого NIL освободится \nдля обычного использования для перевода строки, но \0уже имеет значение в заменах регулярных выражений, поэтому он был перенесен на \n. Следовательно, затем мы продолжаем также сдвигать новую строку с \nна \r(которая в шаблоне регулярного выражения является символом возврата каретки, ASCII 0x0D).

Персонаж | Код ASCII | C представление | Регулярное совпадение | Замена регулярных выражений
------------------------- + ------------ + ----------- ------- + ------------- + ------------------------
ноль | 0x00 | \ 0 | \ 0 | \ п
перевод строки (новая строка Unix) | 0x0a | \ n | \ n | \р
возврат каретки | 0x0d | \ r | \ r | <Неизвестно>

NB: ^M( Ctrl+ V Ctrl+ Mв Linux) вставляет новую строку при использовании в замене регулярного выражения, а не при возврате каретки, как советуют другие (я только что попробовал).

Также обратите внимание, что Vim будет переводить символ перевода строки при сохранении в файл на основе своих настроек формата файла, и это может привести к путанице.

codeshot
источник
11

Из затмения , что ^Mсимволы могут быть встроены в линию, и вы хотите , чтобы преобразовать их в символы новой строки.

:s/\r/\r/g
rickfoosusa
источник
8

Но если нужно заменить, то работает следующее:

:%s/\n/\r\|\-\r/g

Выше каждая следующая строка заменяется следующей строкой, а затем |-и снова новой строкой. Это используется в вики-таблицах.

Если текст выглядит следующим образом:

line1
line2
line3

Это изменено на

line1
|-
line2
|-
line3
Киран К Телукунта
источник
7

Если вам нужно сделать это для всего файла, мне также предложили попробовать из командной строки:

sed 's/\\n/\n/g' file > newfile
Эван Донован
источник
1
Обратите внимание, что для этого требуется GNU sed. Попробуйте printf 'foo\\nbar\n' | sed 's/\\n/\n/g'посмотреть, будет ли он работать в вашей системе. (Благодарю добрых людей из #bash на freenode за это предложение.)
Эван Донован
Да, но вопрос был о Vim. Существует вопрос переполнения стека. Как заменить символ новой строки (\ n) с помощью sed? ,
Питер Мортенсен
5

Вот ответ, который работал для меня. От этого парня:

---- цитирование Используйте редактор vi для вставки символа новой строки вместо


Что-то еще, что я должен сделать и не могу вспомнить, а затем должен искать.

В vi, чтобы вставить символ новой строки в поиск и заменить, выполните следующие действия:

:%s/look_for/replace_with^M/g

Приведенная выше команда заменит все экземпляры «look_for» на «replace_with \ n» (с \ n означает перевод строки).

Чтобы получить «^ M», введите комбинацию клавиш Ctrl+ V, а затем (отпустите все клавиши) нажмите Enterклавишу.


Питер Мортенсен
источник