Почему `^ M` появляется в выводе терминала при просмотре некоторых файлов? - PullRequest
2 голосов
/ 27 апреля 2020

Я пытаюсь отправить файл с помощью curl в конечную точку и сохранить файл на машине.

Отправка curl из Linux и сохранение его на машине работает хорошо, но делает то же самое из Windows добавляет символ ^M к каждому концу строки.

Я печатаю файл перед сохранением и не вижу ^M. Только просмотр файла на удаленном компьютере после сохранения показывает мне ^M.

Простая замена строки не работает.

Почему добавляется ^M? Как я могу предотвратить это?

1 Ответ

3 голосов
/ 27 апреля 2020

Быстрый ответ: возврат каретки . Это безобидный, но слегка раздражающий артефакт того, как Windows кодирует текстовые файлы. Вы можете удалить их из ваших файлов с помощью dos2unix. Вы можете настроить большинство текстовых редакторов так, чтобы они использовали «Unix Концы строк» ​​или «Концы строк LF», чтобы в будущем они не появлялись в новых файлах, созданных вами с Windows ПК.


Длинный ответ (с некоторыми историческими мелочами):

В текстовом файле, когда вы создаете новую строку (нажатием клавиши ввода / возврата), в файл внедряется «разрыв строки». В Unix / Linux это один символ, \ n, перевод строки. На Windows это два последовательных символа '\ r \ n', "возврат каретки", за которыми следует "перевод строки".

Когда физический телетайп терминалов , который вел себя так же, как пишущие машинки, все еще использовались, символ «перевод строки» означал «переместить бумагу на следующую строку», а символ «возврат каретки» означал «сдвинуть каретку полностью, чтобы печатная головка находилась далеко» оставил". С самого начала почти все терминалы телетайпа поддерживали неявный возврат каретки; т. е. запуск перевода строки автоматически вызовет возврат каретки. Разработчики, работающие над тем, что позже превратилось в Windows, решили, что было бы лучше включить явные возвраты каретки, на случай, если (по какой-то причине) телетайп не выполнит один неявно. Разработчики Unix, с другой стороны, решили работать с предположением о неявном возврате каретки.

Возврат каретки и перевод строки - Символы управления ASCII , что означает, что они не имеют видимое представление в виде автономных печатаемых символов, вместо этого они влияют на сам выходной курсор (в данном случае на позицию выходного курсора).

«^ M», которое вы видите, является подставным представлением для каретки символ возврата, используемый программами, которые не полностью «готовят» свой вывод (т. е. не применяют эффекты некоторых управляющих символов ASCII). (Другие управляющие символы имеют другие представления, начинающиеся с «^», и символ «^» также используется для обозначения клавиши «ctrl» в некоторых Unix программах, таких как nano.)

Вы можете используйте dos2unix для преобразования концов строк из стиля Windows в стиль Unix.

$ curl https://example.com/file_with_crlf.txt | dos2unix > file.txt

В некоторых дистрибутивах этот инструмент включен по умолчанию, в других его можно установить через менеджер пакетов (например, в Ubuntu, sudo apt install dos2unix). Также существует пакет, unix2dos, для обратного.

Большинство «умных» текстовых редакторов для кодирования (Sublime, Atom, VS Code, Notepad ++ и др. c.) будет рад читать и писать с окончаниями строк Windows или Unix (это может потребовать изменения некоторых параметров конфигурации). Часто окончания строк автоматически определяются путем сканирования содержимого файла, и обычно новые файлы создаются с исходными окончаниями строк операционной системы (по умолчанию). Даже новая версия Notepad поддерживает окончания строк в стиле Unix. С другой стороны, некоторые инструменты Unix будут давать странные результаты при наличии разрывов строк в стиле Windows. Если ваша кодовая база будет использоваться людьми как в операционных системах Unix, так и Windows, то неплохо будет использовать повсеместно разрывы строк в стиле * 1073.

Git в Windows также имеется дополнительный режим, который проверяет все файлы с Windows разрывами в стиле, но возвращает их обратно с Unix разрывами в стиле.


Примечания сторон (интересно, но не напрямую связано с вашим вопросом):

То, что фактически делает возврат каретки (на современном виртуальном терминале, будь то Windows или Unix), - это перемещение курсора вывода в начало строки. Если вы используете возврат каретки без перевода строки, вы можете «перезаписать» часть уже напечатанной строки.

$ printf "dogdog" ; printf "\rcat\n"
catdog

Некоторые Unix программы используют это для асинхронного обновления части последней строки вывода, для реализации таких вещей, как индикатор обновления в режиме реального времени. Например, curl, который показывает прогресс загрузки на стандартном выводе, если содержимое файла передано в другом месте.

Также: Если у вас был инструмент, который интерпретировал окончания строк Windows в буквальном смысле, насколько это возможно, и вы скормив ей строку с окончаниями строк Unix, такими как "hello \ nworld", вы получите следующий вывод:

hello
     world

К счастью, такие реализации встречаются крайне редко и, как правило, Большинство инструментов Windows могут без проблем визуализировать окончания строк Unix в стиле, как окончания строк Windows в стиле.

...