Новая строка ( часто называемая окончанием строки , концом строки ( EOL ), следующей строкой ( NEL ) или разрывом строки ) — это управляющий символ или последовательность управляющих символов в спецификациях кодировок символов , таких как ASCII , EBCDIC , Unicode и т. д. Этот символ или последовательность символов используется для обозначения конца строки текста и начала новой. [1]
В середине 1800-х годов, задолго до появления телетайпов и телетайпных аппаратов, операторы или телеграфисты азбуки Морзе изобрели и использовали знаки азбуки Морзе для кодирования форматирования текста с пробелами в официальных текстовых сообщениях. В частности, знак азбуки Морзе BT (mnemonic break t ext ), представленный конкатенацией буквенных текстовых символов азбуки Морзе "B" и "T", отправленных без обычного межсимвольного интервала, используется в азбуке Морзе для кодирования и указания новой строки или нового раздела в официальном текстовом сообщении.
Позже, в эпоху современных телетайпов , были разработаны стандартизированные коды управления набором символов для помощи в форматировании текста с пробелами. ASCII был разработан одновременно Международной организацией по стандартизации (ISO) и Американской ассоциацией стандартов (ASA), последняя была предшественницей Американского национального института стандартов (ANSI). В период с 1963 по 1968 год проекты стандартов ISO поддерживали использование либо .mw-parser-output .monospaced{font-family:monospace,monospace}CR+LF, либо LF отдельно в качестве новой строки, в то время как проекты ASA поддерживали только CR + LF .
Последовательность CR + LF обычно использовалась во многих ранних компьютерных системах, которые использовали телетайпные машины — обычно Teletype Model 33 ASR — в качестве консольного устройства, поскольку эта последовательность требовалась для позиционирования этих принтеров в начале новой строки. Разделение новой строки на две функции скрывало тот факт, что печатающая головка не могла вернуться из крайнего правого положения в начало следующей строки вовремя, чтобы напечатать следующий символ. Любой символ, напечатанный после CR , часто печатался как пятно в середине страницы, пока печатающая головка все еще перемещала каретку обратно в первую позицию. «Решение состояло в том, чтобы сделать новую строку двумя символами: CR для перемещения каретки в первый столбец и LF для перемещения бумаги вверх». [2] Фактически, часто было необходимо отправлять дополнительные символы заполнения — лишние CR или NUL — которые игнорируются, но дают печатающей головке время для перемещения к левому полю. Многие ранние видеодисплеи также требовали нескольких символов для прокрутки дисплея.
В таких системах приложениям приходилось напрямую взаимодействовать с телетайпной машиной и следовать ее соглашениям, поскольку концепция скрытия драйверами устройств таких деталей оборудования от приложения еще не была хорошо развита. Поэтому текст обычно составлялся для удовлетворения потребностей телетайпных машин. Большинство миникомпьютерных систем от DEC использовали это соглашение. CP/M также использовала его для печати на тех же терминалах, что и миникомпьютеры. Оттуда MS-DOS (1981) переняла CR + LF от CP/M для обеспечения совместимости, и это соглашение было унаследовано более поздней операционной системой Windows от Microsoft .
Операционная система Multics начала разрабатываться в 1964 году и использовала только LF в качестве новой строки. Multics использовала драйвер устройства для перевода этого символа в любую последовательность, необходимую принтеру (включая дополнительные символы заполнения ), а один байт был более удобен для программирования. То, что кажется более очевидным выбором — CR — не было использовано, поскольку CR предоставлял полезную функцию надпечатки одной строки другой для создания эффектов жирного шрифта , подчеркивания и зачеркивания . Возможно, что еще важнее, использование только LF в качестве разделителя строки уже было включено в проекты окончательного стандарта ISO/IEC 646. Unix последовала практике Multics, а более поздние Unix-подобные системы последовали за Unix. Это создало конфликты между Windows и Unix-подобными операционными системами , в результате чего файлы, составленные в одной операционной системе, не могли быть правильно отформатированы или интерпретированы другой операционной системой (например, сценарий оболочки UNIX, написанный в текстовом редакторе Windows, таком как Notepad [3] [4] ).
Концепции возврата каретки (CR) и перевода строки (LF) тесно связаны и могут рассматриваться как по отдельности, так и вместе. В физических носителях пишущих машинок и принтеров для создания новой строки на странице необходимы две оси движения: «вниз» и «поперек» . Хотя конструкция машины (пишущей машинки или принтера) должна рассматривать их по отдельности, абстрактная логика программного обеспечения может объединять их вместе как одно событие. Вот почему перевод строки в кодировке символов может быть определен как и объединен в один (обычно называемый или ).CR
LF
CR+LF
CRLF
Некоторые наборы символов предоставляют отдельный код символа новой строки. Например, EBCDIC предоставляет код символа NL в дополнение к кодам CR и LF . Unicode , в дополнение к управляющим кодам ASCII CR и LF , также предоставляет управляющий код «следующей строки» ( NEL ), а также управляющие коды для маркеров «разделителя строк» и «разделителя абзацев». Unicode также содержит печатаемые символы для визуального представления перевода строки ␊, возврата каретки ␍ и других управляющих кодов C0 (а также общего символа новой строки ) в блоке Control Pictures .
0x85
#
Многие протоколы связи имеют своего рода соглашение о новой строке. В частности, протоколы, опубликованные Internet Engineering Task Force (IETF), обычно используют последовательность ASCII CRLF.
В некоторых старых протоколах за новой строкой может следовать символ контрольной суммы или четности.
Стандарт Unicode определяет ряд символов, которые соответствующие приложения должны распознавать как символы конца строки: [9]
Хотя это может показаться слишком сложным по сравнению с таким подходом, как преобразование всех символов конца строки в один символ (например, LF ), поскольку Unicode разработан для сохранения всей информации при преобразовании текстового файла из любой существующей кодировки в Unicode и обратно ( целостность при передаче ), Unicode должен делать те же различия между переносами строк, создаваемыми другими кодировками.
Например: NL является частью EBCDIC , который использует код 0x15 ; он обычно отображается в Unicode NEL , 0x85 , который является управляющим символом в наборе управления C1 . [10] Как таковой, он определен ECMA 48, [11] и распознается кодировками, соответствующими ISO/IEC 2022 (что эквивалентно ECMA 35). [12] Набор управления C1 также совместим с ISO-8859-1 . [ необходима цитата ] Подход, принятый в стандарте Unicode, позволяет сохранять информацию при двустороннем преобразовании, при этом позволяя приложениям распознавать все возможные типы ограничителей строк.
Распознавание и использование кодов новой строки больше 0x7F ( NEL , LS и PS ) нечасто выполняется. Они представляют собой несколько байтов в UTF-8 , а код для NEL использовался как символ многоточия ( ) в Windows-1252 . Например:…
Специальные символы Unicode U+2424 ( СИМВОЛ ПЕРЕХОДА НА НОВУЮ СТРОКУ , ), U+23CE ( СИМВОЛ ВОЗВРАТА КАРЕТКИ , ), U+240D ( СИМВОЛ ВОЗВРАТА КАРЕТКИ , ) и U+240A ( СИМВОЛ ПЕРЕВОДА СТРОКИ , ) являются глифами, предназначенными для представления видимого пользователю символа читателю документа, и поэтому сами по себе не распознаются как символ новой строки.
⏎
␍
␊
Для облегчения создания переносимых программ языки программирования предоставляют некоторые абстракции для работы с различными типами последовательностей новой строки, используемых в разных средах.
Язык C предоставляет escape-последовательности '\n' (перевод строки) и '\r' (возврат каретки). Однако они не обязаны быть эквивалентными управляющим символам ASCII LF и CR . Стандарт C гарантирует только две черты:
На платформах операционной системы Unix , где зародился язык C, собственная последовательность новой строки — ASCII LF ( 0x0A ), поэтому '\n' просто определено как это значение. Поскольку внутреннее и внешнее представление идентичны, перевод, выполняемый в текстовом режиме, является пустой операцией , а в Unix нет понятия текстового режима или двоичного режима. Это заставило многих программистов, которые разрабатывали свое программное обеспечение на системах Unix, просто полностью игнорировать это различие, что привело к коду, который непереносим на другие платформы.
Функцию библиотеки C fgets () лучше избегать в двоичном режиме, поскольку любой файл, записанный без соглашения о новой строке Unix, будет неправильно прочитан. Кроме того, в текстовом режиме любой файл, записанный без собственной последовательности новой строки системы (например, файл, созданный в системе Unix, а затем скопированный в систему Windows), также будет неправильно прочитан.
Другая распространенная проблема — использование '\n' при общении с использованием интернет-протокола, который предписывает использование ASCII CR + LF для завершения строк. Запись '\n' в поток текстового режима работает правильно в системах Windows, но производит только LF в Unix и что-то совершенно иное в более экзотических системах. Использование "\r\n" в двоичном режиме немного лучше.
Многие языки, такие как C++ , Perl , [20] и Haskell, обеспечивают ту же интерпретацию '\n', что и C. C++ имеет альтернативную модель ввода-вывода (I/O) , в которой манипулятор std::endl может использоваться для вывода новой строки (и очистки буфера потока).
Java , PHP , [21] и Python [22] предоставляют последовательность '\r\n' (для ASCII CR + LF ). В отличие от C, они гарантированно представляют значения U+000D и U+000A , соответственно.
Библиотеки ввода-вывода (I/O) Java не транслируют их прозрачно в платформенно-зависимые последовательности новой строки на входе или выходе. Вместо этого они предоставляют функции для записи полной строки, которые автоматически добавляют собственную последовательность новой строки, и функции для чтения строк, которые принимают любой из CR , LF , или CR + LF в качестве терминатора строки (см. BufferedReader.readLine()). Метод System.lineSeparator() может использоваться для извлечения базового разделителя строки.
Пример:
String eol = System.lineSeparator (); String lineColor = " Цвет : Красный" + eol ;
Python допускает «универсальную поддержку новой строки» при открытии файла для чтения, при импорте модулей и при выполнении файла. [23]
Некоторые языки создали специальные переменные , константы и подпрограммы для облегчения перехода на новую строку во время выполнения программы. В некоторых языках, таких как PHP и Perl , для выполнения замены escape-последовательностей, включая '\n' и '\r' , требуются двойные кавычки . В PHP, чтобы избежать проблем с переносимостью, последовательности перехода на новую строку должны быть выданы с использованием константы PHP_EOL. [24]
Пример на C# :
string eol = Environment . NewLine ; string lineColor = "Цвет: Красный" + eol ; string eol2 = "\n" ; string lineColor2 = "Цвет: Синий" + eol2 ;
Различные соглашения о переводе строк приводят к некорректному отображению текстовых файлов, переданных между системами разных типов.
Текст в файлах, созданных с помощью программ, распространенных в Unix-подобных системах или классической Mac OS , отображается как одна длинная строка в большинстве программ, распространенных в MS-DOS и Microsoft Windows, поскольку они не отображают один line feed
или один символ carriage return
в качестве переноса строки.
И наоборот, при просмотре файла, созданного на компьютере Windows, в Unix-подобной системе дополнительный CR может отображаться как второй перенос строки, как ^M или как <cr> в конце каждой строки.
Кроме того, программы, отличные от текстовых редакторов, могут не принять файл, например, какой-либо файл конфигурации, закодированный с использованием иностранного соглашения о новой строке, как допустимый файл.
Проблему может быть трудно обнаружить, поскольку некоторые программы обрабатывают иностранные переводы строк правильно, а другие — нет. Например, компилятор может выдать ошибку со скрытыми синтаксическими ошибками, даже если исходный файл выглядит правильно при отображении на консоли или в редакторе . Современные текстовые редакторы обычно распознают все разновидности перевода строк CR + LF и позволяют пользователям выполнять преобразование между различными стандартами. Веб-браузеры обычно также способны отображать текстовые файлы и веб-сайты, которые используют различные типы перевода строк.
Даже если программа поддерживает различные соглашения о новой строке, эти функции часто недостаточно помечены, описаны или задокументированы. Обычно меню или выпадающий список, перечисляющие различные соглашения о новой строке, отображаются пользователям без указания того, будет ли выбор переинтерпретировать, временно преобразовывать или постоянно преобразовывать новые строки. Некоторые программы неявно преобразуют при открытии, копировании, вставке или сохранении — часто непоследовательно.
Большинство текстовых интернет- протоколов (включая HTTP , SMTP , FTP , IRC и многие другие) требуют использования ASCII CR + LF ( '\r\n' , 0x0D 0x0A ) на уровне протокола, но рекомендуют, чтобы толерантные приложения также распознавали одинокий LF ( '\n' , 0x0A ). Несмотря на предписанный стандарт, многие приложения ошибочно используют управляющую последовательность новой строки C '\n' ( LF ) вместо правильной комбинации управляющих последовательностей возврата каретки и новой строки '\r\n' ( CR + LF ) (см. раздел Новая строка в языках программирования выше). Это случайное использование неправильных управляющих последовательностей приводит к проблемам при попытке взаимодействия с системами, придерживающимися более строгой интерпретации стандартов вместо предлагаемой толерантной интерпретации. Одной из таких нетерпимых систем является почтовый агент qmail , который активно отказывается принимать сообщения от систем, отправляющих голый LF вместо требуемых CR + LF . [25]
Стандартный формат интернет-сообщений [26] для электронной почты гласит: «CR и LF ДОЛЖНЫ встречаться только вместе как CRLF; они НЕ ДОЛЖНЫ появляться независимо в теле». Различия между реализациями SMTP в том, как они обрабатывают чистые символы LF и/или чистые символы CR, привели к атакам с подменой SMTP, называемым «SMTP-контрабандой». [27]
Протокол передачи файлов может автоматически преобразовывать символы новой строки в файлах, передаваемых между системами с различными представлениями новой строки, когда передача выполняется в «режиме ASCII». Однако передача двоичных файлов в этом режиме обычно имеет катастрофические результаты: любое появление последовательности байтов новой строки, которая не имеет семантики терминатора строки в этом контексте, а является просто частью обычной последовательности байтов, будет преобразовано в любое представление новой строки, используемое другой системой, что фактически повреждает файл. Клиенты FTP часто используют некоторую эвристику (например, проверку расширений имен файлов ) для автоматического выбора двоичного или ASCII-режима, но в конечном итоге пользователи должны убедиться, что их файлы передаются в правильном режиме. Если есть какие-либо сомнения относительно правильного режима, следует использовать двоичный режим, так как в этом случае файлы не будут изменены FTP, хотя они могут отображаться неправильно. [28]
Текстовые редакторы часто используются для преобразования текстового файла между различными форматами новой строки; большинство современных редакторов могут читать и записывать файлы, используя, по крайней мере, различные соглашения ASCII CR / LF .
Например, редактор Vim может сделать файл совместимым с текстовым редактором Windows Notepad. В vim
: установить формат файла = dos : вк
Редакторы могут быть непригодны для конвертации больших файлов или пакетного конвертирования многих файлов. Для больших файлов (в Windows NT) часто используется следующая команда:
D:\> ВВЕДИТЕ unix_file | НАЙТИ /V "" > dos_file
Специальные программы для преобразования файлов между различными соглашениями о новой строке включают unix2dos и dos2unix , mac2unix и unix2mac , mac2dos и dos2mac , а также flip . [29] Команда tr доступна практически в любой Unix-подобной системе и может использоваться для выполнения произвольных операций замены отдельных символов. Текстовый файл DOS/Windows можно преобразовать в формат Unix, просто удалив все символы ASCII CR с помощью
$ tr -d '\r' < входной_файл > выходной_файл
или, если текст содержит только символы переноса строк CR , преобразуя все символы переноса строк CR в символы переноса строк LF с помощью
$ tr '\r' '\n' < входной_файл > выходной_файл
Те же задачи иногда выполняются с помощью awk , sed или Perl , если на платформе имеется интерпретатор Perl:
$ awk '{sub("$","\r\n"); printf("%s",$0);}' inputfile > outputfile # UNIX в DOS (добавление CR в ОС на базе Linux и BSD, не имеющих расширений GNU) $ awk '{gsub("\r",""); print;}' inputfile > outputfile # DOS в UNIX (удаление CR в ОС на базе Linux и BSD, в которых нет расширений GNU) $ sed -e 's/$/\r/' inputfile > outputfile # UNIX в DOS (добавление CR в ОС на базе Linux, в которых используются расширения GNU) $ sed -e 's/\r$//' inputfile > outputfile # DOS в UNIX (удаление CR в ОС на базе Linux, в которых используются расширения GNU) $ perl -pe 's/\r?\n|\r/\r\n/g' inputfile > outputfile # Преобразование в DOS $ perl -pe 's/\r?\n|\r/\n/g' inputfile > outputfile # Преобразование в UNIX $ perl -pe 's/\r?\n|\r/\r/g' inputfile > outputfile # Преобразование в старый Mac
Команда file может определить тип окончания строки:
$ file myfile.txt myfile.txt: ASCII английский текст с символами конца строки CRLF
Команда Unix egrep (расширенная команда grep) может использоваться для печати имен файлов Unix или DOS (предполагается, что это только файлы в стиле Unix и DOS, а не классические файлы в стиле Mac OS):
$ egrep -L '\r\n' myfile.txt # показать файл в стиле UNIX (завершается LF) $ egrep -l '\r\n' myfile.txt # показать файл в стиле DOS (завершается CRLF)
Другие инструменты позволяют пользователю визуализировать символы EOL:
$ od -a myfile.txt $ cat -e myfile.txt $ cat -v myfile.txt $ hexdump -c myfile.txt
Два способа просмотра новых строк, оба из которых являются самосогласованными , заключаются в том, что новые строки либо разделяют строки, либо завершают строки. Если новая строка считается разделителем, то после последней строки файла не будет новой строки. У некоторых программ возникают проблемы с обработкой последней строки файла, если она не завершается новой строкой. С другой стороны, программы, которые ожидают, что новая строка будет использоваться в качестве разделителя, будут интерпретировать конечную новую строку как начало новой (пустой) строки. И наоборот, если новая строка считается терминатором, то все текстовые строки, включая последнюю, должны завершаться новой строкой. Если конечная последовательность символов в текстовом файле не является новой строкой, то последняя строка файла может считаться неправильной или неполной текстовой строкой, или файл может считаться неправильно усеченным.
В тексте, предназначенном в первую очередь для чтения людьми с использованием программного обеспечения, реализующего функцию переноса слов , символ новой строки обычно требуется сохранять только в том случае, если требуется перенос строки, независимо от того, поместится ли следующее слово на той же строке, например, между абзацами и в вертикальных списках. Поэтому в логике обработки текста и большинства текстовых редакторов символ новой строки используется как разрыв абзаца и известен как «жесткий возврат», в отличие от «мягких возвратов», которые динамически создаются для реализации переноса слов и изменяются с каждым экземпляром отображения. Во многих приложениях существует отдельный управляющий символ , называемый «ручной перенос строки», для принудительного переноса строк внутри одного абзаца. Глифом для управляющего символа для жесткого возврата обычно является pilcrow (¶), а для ручного переноса строки обычно является стрелка возврата каретки (↵).
RI ( U +008D REVERSE LINE FEED , [30] ISO/IEC 6429 8D, десятичный 141) используется для перемещения позиции печати на одну строку назад (путем обратной подачи бумаги или перемещения курсора дисплея на одну строку вверх), чтобы другие символы могли быть напечатаны поверх существующего текста. Это может быть сделано для того, чтобы сделать их более жирными или добавить подчеркивания, зачеркивания или другие символы, такие как диакритические знаки .
Аналогично, PLD ( U +008B PARTIAL LINE FORWARD, десятичный 139) и PLU ( U +008C PARTIAL LINE BACKWARD, десятичный 140) могут использоваться для продвижения или реверсирования позиции печати текста на некоторую долю вертикального интервала между строками (обычно на половину). Их можно использовать в комбинации для нижних индексов (путем продвижения и последующего реверсирования) и верхних индексов (путем реверсирования и последующего реверсирования), а также они могут быть полезны для печати диакритических знаков.
П]осле десятилетий разочарований и необходимости загружать настоящий текстовый редактор для изменения одной строки в файле конфигурации с Linux-компьютера Microsoft обновила Notepad, чтобы он мог обрабатывать символы конца строки, используемые в средах Unix, Linux и macOS.
и в случае с любым изменением в давно известном инструменте, есть вероятность, что это новое поведение может не сработать в ваших сценариях, или вы можете предпочесть отключить это новое поведение и вернуться к исходному поведению Блокнота. Для этого вы можете изменить [...ключи реестра...], чтобы настроить то, как Блокнот обрабатывает вставку текста, и какой символ EOL использовать при нажатии Enter/Return
В случае сомнений передавайте в двоичном режиме.