Если вы когда-нибудь открывали текстовый файл в "не той" операционной системе и видели вместо нормальных переносов строк странные символы вроде ^M или всё содержимое "в одну строку", - поздравляем, вы столкнулись с классической проблемой CR, LF и CRLF.


Что такое CR и LF?

Когда компьютеры только появились, в печатных устройствах (например, телетайпах и принтерах) существовало два отдельных действия:

  • CR (Carriage Return) - "возврат каретки". Возвращает печатающую головку в начало строки.
    Код: 0x0D (в десятичной системе - 13).
  • LF (Line Feed) - "подача строки". Перемещает бумагу на одну строку вниз.
    Код: 0x0A (в десятичной системе - 10).

Чтобы напечатать новую строку, телетайпам нужно было сделать оба действия: вернуть каретку и подать бумагу. Именно отсюда взялось сочетание CR + LF (0x0D0A).


Как получилось, что системы используют разные варианты

С развитием компьютеров каждая платформа пошла своим путём:

- Windows

Перевод строки: CR LF
Символы: \r\n
Hex-коды: 0x0D0A

- Unix / Linux / macOS (современные)

Перевод строки: LF
Символы: \n
Hex-коды: 0x0A

- Классический macOS (до OS X)

Перевод строки: CR
Символы: \r
Hex-коды: 0x0D

Windows осталась верна историческому подходу (использует оба символа), а Unix-системы решили упростить жизнь и ограничились только LF. Старые версии macOS (до OS X) пошли своим путём и использовали только CR, но с переходом на Unix-ядро перешли на LF.


Почему это всё ещё важно

- Git и репозитории.

Если не настроить core.autocrlf, можно получить "лишние" изменения при каждом коммите, когда Git автоматически конвертирует переводы строк.

- Текстовые редакторы.

VS Code, Sublime Text, Notepad++ и другие показывают формат перевода строк (LF, CRLF). Можно легко поменять тип внизу окна.

- Скрипты и конфигурации.

Bash на Linux может "споткнуться" на файле с CRLF, потому что \r будет воспринят как лишний символ. Часто это происходит при копировании файлов с Windows.


Как определить тип перевода строк

В Linux это легко сделать с помощью file или cat -A:

file myfile.txt
cat -A myfile.txt

Пример вывода:

  • LF: $ в конце строк
  • CRLF: ^M$ в конце строк

CR, LF и CRLF - это пережиток эпохи печатных машинок, который до сих пор влияет на разработку.

Главное - понимать, почему разные системы ведут себя по-разному, и следить за консистентностью в проектах. Тогда никаких "лишних ^M" больше не будет.


Source: Orkhan Alishov's notes