新队
newline (通常称为线路结束,线路结束( EOL ),下一行( NEL )或线路断开)是在字符编码规范(例如ASCII , ebcdic , unicode等)中的控制字符或序列。或一系列字符,用于表示文本线的末尾和新的文本开始。
历史
在1800年代中期,在传送机和电视机的出现之前,摩尔斯代码运营商或电信师发明并使用了Morse Code Prosigns来编码正式书面文本消息中的白空间文本格式。特别是由字面文本摩尔斯语代码“ b ”和“ t ”字符的串联表示,在摩尔斯语代码中使用了不正常的字符间距,以编码并指示一条新行或正式文本消息中的新部分。
后来,在现代电信器时代,制定了标准化的角色集控制代码,以帮助进行白空间文本格式。 ASCII是由国际标准化组织(ISO)和美国标准协会(ASA)同时开发的,后者是美国国家标准研究所(ANSI)的前身组织。在1963年至1968年期间,ISO草案标准支持使用任何一种CR+ LF或LF单独用作新线,而ASA起草仅支持CR+ LF。
序列Cr + LF通常用于许多早期的计算机系统,这些计算机系统采用了电视机机器(通常是电视33 ASR)作为控制台设备,因为需要此序列才能将这些打印机定位在新线路开始时。将新线分为两个函数掩盖了一个事实,即打印头无法从最右边返回到下一行的开头,以打印下一个字符。当打印头仍将马车移回第一个位置时, CR后打印的任何字符通常都会在页面中间打印为污迹。 “解决方案是使新线两个字符: CR将马车移至第一栏,而LF则将纸移动。”实际上,通常有必要发送额外的字符(具有自然的CRS或NUL),而这些字符被忽略了,但要给打印头的时间移至左边。许多早期的视频显示还需要多个字符时间才能滚动显示。
在此类系统上,应用程序必须直接与电视机机器进行交谈,并遵循其惯例,因为设备驱动程序的概念隐藏了该应用程序中的硬件详细信息。因此,常规编写文本以满足电视机的需求。 DEC的大多数微型计算机系统都使用了此公约。 CP/M还使用了它来打印在微型计算机使用的相同端子上。从那里开始, MS-DOS (1981)采用了CP/M的CR + LF,以兼容,该约定是由Microsoft后来的Windows操作系统继承的。
Multics操作系统于1964年开始开发,并单独使用LF作为新线路。 Multics使用设备驱动程序将该字符转换为打印机所需的任何顺序(包括额外的填充字符),而单个字节对于编程更方便。似乎不使用CR的一个更明显的选择,因为CR提供了用一条线覆盖一条线以创建大胆,下划线和罢工效果的有用功能。也许更重要的是,仅将LF用作线路终止器的使用已经被纳入最终ISO/IEC 646标准的草稿中。 Unix遵循了多项式实践,后来类似Unix的系统遵循Unix。这造成了Windows和类似Unix的操作系统之间的冲突,在此过程中,在一个操作系统上组成的文件无法通过另一个操作系统的格式或解释(例如,在Windows Text Editor(如Notepad )中编写的Unix Shell脚本)。
表示
托架返回(CR)和线馈电(LF)的概念密切相关,可以分开或一起考虑。在打字机和打印机的物理介质中,需要两个运动轴“向下”和“跨”,以在页面上创建新的线条。尽管机器的设计(打字机或打印机)必须单独考虑它们,但软件的抽象逻辑可以将它们结合在一起,作为一个事件。这就是为什么字符编码中的newline可以定义为CR
和LF
合并成一个(通常称为CR+LF
或者CRLF
).
一些字符集提供了单独的新线字符代码。例如, EBCDIC除了CR和LF代码外提供了NL字符代码。除了提供ASCII CR和LF控制代码外, Unicode还提供了“ Next Line”( NEL )控制代码,以及“线分隔符”和“段落分隔符”标记的控制代码。
作业系统 | 字符编码 | 缩写 | 十六进位 | DEC值 | 逃脱序列 |
---|---|---|---|---|---|
UNIX和UNIX式系统( Linux , MacOS , FreeBSD , AIX , Xenix等), Multics , Beos , Amiga , Risc OS等 | ASCII | 如果 | 0a | 10 | \ n |
Microsoft Windows , DOS ( MS-DOS , PC DOS等), ATARI TOS , DEC TOPS-10 , RT-11 , CP/M , MP/M , OS/2 , Symbian OS , Palm OS ,Amstrad CPC和Amstrad CPC和大多数其他早期的非UNIX和非IBM操作系统 | cr lf | 0d 0a | 13 10 | \ r \ n | |
Commodore 8位机器( C64 , C128 ), Acorn BBC , ZX Spectrum , TRS-80 , Apple II系列, Oberon , Classic Mac OS ,MIT LISP机器和OS-9 | Cr | 0d | 13 | \ r | |
QNX PREPOSIX实现(版本<4) | 卢比 | 1e | 30 | \036 | |
Acorn BBC和RISC OS牵引文本输出 | lf cr | 0a 0d | 10 13 | \ n \ r | |
Atari 8位机器 | atascii | EOL | 9b | 155 | |
IBM大型机系统,包括Z/OS ( OS/390 )和IBM I ( OS/400 ) | EBCDIC | NL | 15 | 21 | \025 |
ZX80和ZX81 ( Sinclair Research Ltd的家用计算机) | ZX80 / ZX81专有编码 | 76 | 118 |
- EBCDIC系统 - 包括Z/OS ( OS/390 )和IBM I ( OS/400 )在内的IBM大型机系统 - 使用NL (New Line, 0x15 )作为结合线路馈电和运输返回功能的字符。等效的Unicode字符(
0x85
)称为NEL (下行)。 EBCDIC还具有称为CR和LF的控制字符,但是LF ( 0x25 )的数值与ASCII( 0x0A )使用的字符不同。此外,某些EBCDIC变体也使用NL ,但为字符分配了不同的数字代码。但是,这些操作系统使用基于记录的文件系统,该文件将文本文件存储为每行的一个记录。在大多数文件格式中,实际上没有存储线路终止器。 - CDC 6000系列的操作系统在60位单词的末尾将Newline定义为两个或多个零值的六位字符。一些配置还将零值的字符定义为结肠字符,结果可以将多个结肠解释为新线,具体取决于位置。
- RSX-11和OpenVM还使用基于记录的文件系统,该文件将文本文件存储为每行的一个记录。在大多数文件格式中,实际上没有存储线路终止器,但是记录管理服务设施在通过应用程序检索时可以透明地将终结器添加到每条线时。记录本身可以包含相同的行终端字符,根据应用程序,可以将其视为功能或滋扰。 RMS不仅存储记录,而且还存储有关记录分隔符的元数据,以使文件更复杂,以使事情变得更复杂(因为文件可以具有固定的长度记录,这些记录由计数或由特定字符终止的记录前缀或记录。 )。这些位不是通用的,因此尽管它们可以指定CR LF或LF甚至CR是线路终结器,但它们无法替代其他代码。
- 固定线长度由一些早期的大型机操作系统使用。例如,在这样的系统中,假定每72或80个字符一次隐式末端。没有存储Newline角色。如果从外界导入文件,则必须用空格填充线长的线短,而线长的时间长于线长度。这模仿了打孔卡的使用,每行都存储在单独的卡上,通常在每张卡上有80列,通常在第73–80列中有序列编号。这些系统中的许多系统在下一个记录的开始中添加了一个马车控制字符。这可能表明下一个记录是以前记录启动的线路的延续,还是新的行启动,还是应该覆盖上一行(类似于CR )。通常这是一个普通的印刷字符,例如
#
因此,这不能用作行中的第一个字符。一些早期的打印机直接在发送给他们的记录中解释了这些字符。
通信协议
许多通信协议都有某种新的行惯例。特别是,由Internet工程工作组(IETF)发布的协议通常使用ASCII CRLF序列。
在某些较旧的协议中,新行可以是校验和奇偶校验字符。
Unicode
Unicode标准定义了许多符合应用程序的字符应识别为线路终结者:
- 如果: 线供稿, U+000A
- VT : 垂直选项卡, u+000b
- FF : form feed , U+000C
- CR : 马车返回, U+000D
- CR + LF : CR ( U+000D ),然后是LF ( U+000A )
- 内尔: 下一行, U+0085
- LS : 线分离器, u+2028
- PS : 段落分离器, u+2029
与将所有线路终止器转换为单个字符(例如LF )之类的方法相比,它似乎看起来过于复杂,因为Unicode旨在在将文本文件从任何现有编码转换为Unicode和Back(往返)时,为保留所有信息。完整性),Unicode需要在其他编码进行的线路断裂之间做出相同的区分。
例如: NL是使用代码0x15的EBCDIC的一部分;通常将其映射到Unicode NEL , 0x85 ,它是C1控制集中的控制字符。因此,它由ECMA 48定义,并通过符合ISO/IEC 2022的编码(等效于ECMA 35)来识别。 C1控制集也与ISO-8859-1兼容。 Unicode标准中采用的方法允许往返转换是信息提供信息的,同时仍使应用程序能够识别所有可能的线路终止器类型。
识别和使用大于0x7F ( NEL , LS和PS )的NEWLINE代码通常不经常完成。它们是UTF-8中的多个字节, NEL的代码已用作省略号(…
) Windows-1252中的字符。例如:
- Ecmascript接受LS和PS作为线路断裂,但认为U+0085 ( NEL ) Whitespace而不是线路断路。
- JSON允许在字符串中使用LS和PS字符,而ES2019之前的Ecmascript将其视为新线,因此将其视为非法语法。
- YAML不再将它们视为1.2版本的线路断裂,以便与JSON兼容。
- Windows Notepad是Microsoft Windows的默认文本编辑器,并未将NEL , LS或PS的任何内容视为线路断裂。
- GEDIT是GNOME桌面环境的默认文本编辑器,将LS和PS视为LS和NEL,而不是NEL 。
Unicode特殊字符u+2424 (Newline的符号,
), u+23ce (返回符号,⏎
), u+240d (返回马车的符号,␍
)和u+240a (线馈的符号,␊
)是旨在向文档读者展示用户可见字符的字形,因此不被认为自己是新线。
在编程语言中
为了促进便携式程序的创建,编程语言提供了一些抽象来处理在不同环境中使用的不同类型的新线序列。
C编程语言提供了逃生序列“ \ n” (newline)和“ \ r” (马车返回)。但是,这些不需要等同于ASCII LF和CR控制字符。 C标准只保证了两件事:
- 这些逃生序列中的每一个都映射到一个唯一可以存储在单个char值中的唯一实现定义的数字。
- 在文本模式下写入文件,设备节点或套接字/fifo时, '\ n'透明地转换为系统使用的本机新线序列,可能比一个字符更长。在文本模式下读取时,本机新线序列会转回“ \ n” 。在二进制模式下,没有进行翻译,并且直接输出了由“ \ n”产生的内部表示。
在c起源的unix平台上,本机新线序列为ascii lf ( 0x0a ),因此“ \ n”被简单地定义为该值。由于内部和外部表示形式相同,在文本模式下执行的翻译是一个no-op ,unix没有文本模式或二进制模式的概念。这导致许多程序员在UNIX系统上开发软件只是为了完全忽略了区别,从而导致代码无法移植到不同平台。
在二进制模式下,最好避免使用C库函数fgets () ,因为任何未使用Unix Newline约定编写的文件都会被误读。同样,在文本模式下,也误读了任何未使用系统的本机newline序列编写的文件(例如在Unix系统上创建的文件,然后复制到Windows系统)。
另一个常见的问题是使用“ \ n”使用Internet协议时使用“ \ n”,该协议要求使用ASCII CR + LF用于结束线。将“ \ n”写入文本模式流在Windows系统上正常工作,但仅在UNIX上产生LF ,并且在更外来的系统上完全不同。在二进制模式下使用“ \ r \ n”稍好一些。
许多语言(例如C ++ , Perl和Haskell)提供了与C. C ++具有替代性I /O模型相同的解释,其中Manipulator std :: endl可以使用来输出新线缓冲)。
Java , PHP和Python提供了“ \ r \ n'序列(对于ASCII CR + LF )。与C相反,保证这些值分别代表U+000D和U+000A的值。
Java I/O库不会透明地将其转换为输入或输出上的平台依赖性新线序列。取而代之的是,它们提供了编写完整行的功能,该函数会自动添加本机新线序列,以及用于读取CR , LF或CR + LF作为线路终结器的线路的函数(请参阅BufferedReader.Readline () )。 System.lineseparator()方法可用于检索基础线分离器。
例子:
String eol = System.lineSeparator();
String lineColor = "Color: Red" + eol;
Python允许在打开用于读取的文件,导入模块以及执行文件时“通用新线支持”。
某些语言创建了特殊的变量,常数和子例程,以促进程序执行过程中的新线。在某些语言(例如PHP和Perl)中,需要双引号才能对所有逃生序列进行逃生替换,包括'\ n'和'\ r' 。在PHP中,为了避免可移植性问题,应使用PHP_EOL常数发出newline序列。
C#中的示例:
string eol = Environment.NewLine;
string lineColor = "Color: Red" + eol;
string eol2 = "\n";
string lineColor2 = "Color: Blue" + eol2;
不同的新线格式的问题
不同的Newline约定导致文本文件已在不同类型的系统之间传输的文本文件被错误地显示。
在使用类似于Unix的或经典Mac OS上常见的程序创建的文件中的文本,在MS-DOS和Microsoft Windows常见的大多数程序上显示为一条长行,因为这些程序没有显示单个line feed
或一个carriage return
作为线路休息。
相反,当查看源自Unix式系统上Windows计算机的文件时,额外的CR可能会显示为第二个行断路,或在每行末尾显示为<m> 。
此外,除文本编辑器以外的其他程序可能不接受文件,例如某些使用外国纽线约定编码的配置文件作为有效的文件。
问题可能很难发现,因为有些程序正确处理外国新线,而另一些程序则不能。例如,即使在控制台或编辑器中显示源文件时,编译器可能会因晦涩的语法错误而失败。现代文本编辑者通常会识别CR + LF新线的所有口味,并允许用户在不同的标准之间进行转换。 Web浏览器通常还能够显示使用不同类型的新线的文本文件和网站。
即使程序支持不同的Newline约定,这些功能通常也没有足够的标记,描述或记录。通常,将向用户展示菜单或组合框,枚举不同的Newline约定,而无需指示选择是否会重新解释,暂时转换或永久转换新线。一些程序通常会隐含地转换,复制,粘贴或保存 - 通常不一致。
大多数文本Internet协议(包括HTTP , SMTP , FTP , IRC和其他许多)要求在协议级别使用ASCII CR + LF ('\ r \ n' , 0x0d 0x0a ) ( '\ n' , 0x0a )。尽管有规定的标准,但许多应用程序错误地使用c newline逃生序列'\ n' ( lf ),而不是运输返回逃生和纽线逃生序列'\ r \ n' ( CR + lf )的正确组合上面的编程语言)。当试图与遵守标准更严格的解释而不是建议的宽容解释的系统交流时,这种意外使用错误的逃生序列会导致问题。这样一个不宽容的系统是Qmail邮件传输代理,它积极拒绝接受来自发送裸露LF而不是所需的CR + LF的系统的消息。
电子邮件的标准互联网消息格式指出:“ CR和LF必须仅作为CRLF一起出现;它们不能独立出现在身体中”。 SMTP实现如何处理裸露的LF和/或Bare CR角色之间的差异导致SMTP欺骗攻击,称为“ SMTP走私”。
当在“ ASCII模式”完成传输时,文件传输协议可以自动转换在具有不同NEWLINE表示的系统之间的文件中的Newlines。但是,在此模式下传输二进制文件通常会产生灾难性的结果:Newline字节序列的任何出现(在这种情况下没有线终结器语义,但只是正常字节序列的一部分),都将翻译成任何Newline表示形式另一个系统使用,有效损坏文件。 FTP客户端通常采用一些启发式方法(例如,对文件名扩展的检查)自动选择二进制模式或ASCII模式,但最终取决于用户以确保其文件以正确的模式传输。如果对正确的模式有任何疑问,应使用二进制模式,因为FTP将不会更改文件,尽管它们可能会错误地显示。
Newline格式之间的转换
文本编辑器通常用于在不同的newline格式之间转换文本文件;大多数现代编辑者都可以使用不同的ASCII CR / LF约定读写文件。
例如,编辑器VIM可以使文件与Windows Notepad Text Editor兼容。在VIM内
:set fileformat=dos
:wq
编辑不适合转换较大的文件或许多文件的大量转换。对于较大的文件(在Windows NT/2000/XP上),经常使用以下命令:
D:\>TYPE unix_file | FIND /V "" > dos_file
在不同的Newline约定之间转换文件的特殊目的程序包括UNIX2DOS和DOS2UNIX , MAC2UNIX和UNIX2MAC , MAC2DOS和DOS2MAC以及FLIP 。 TR命令几乎可以在每个类似于Unix的系统上使用,可用于对单个字符执行任意替换操作。 DOS/Windows文本文件可以通过简单地删除所有ASCII CR字符来转换为UNIX格式
$ tr -d '\r' < inputfile > outputfile
或者,如果文本只有CR新线,则通过将所有CR新线转换为LF
$ tr '\r' '\n' < inputfile > outputfile
如果平台具有Perl解释器,则有时会使用尴尬, SED或Perl执行相同的任务:
$ awk '{sub("$","\r\n"); printf("%s",$0);}' inputfile > outputfile # UNIX to DOS (adding CRs on Linux and BSD based OS that haven't GNU extensions)
$ awk '{gsub("\r",""); print;}' inputfile > outputfile # DOS to UNIX (removing CRs on Linux and BSD based OS that haven't GNU extensions)
$ sed -e 's/$/\r/' inputfile > outputfile # UNIX to DOS (adding CRs on Linux based OS that use GNU extensions)
$ sed -e 's/\r$//' inputfile > outputfile # DOS to UNIX (removing CRs on Linux based OS that use GNU extensions)
$ perl -pe 's/\r?\n|\r/\r\n/g' inputfile > outputfile # Convert to DOS
$ perl -pe 's/\r?\n|\r/\n/g' inputfile > outputfile # Convert to UNIX
$ perl -pe 's/\r?\n|\r/\r/g' inputfile > outputfile # Convert to old Mac
文件命令可以标识行末尾的类型:
$ file myfile.txt
myfile.txt: ASCII English text, with CRLF line terminators
UNIX EGREP (扩展GREP)命令可用于打印UNIX或DOS文件的文件名(仅假设UNIX和DOS型文件,没有经典的Mac OS型文件):
$ egrep -L '\r\n' myfile.txt # show UNIX style file (LF terminated)
$ egrep -l '\r\n' myfile.txt # show DOS style file (CRLF terminated)
其他工具允许用户可视化EOL字符:
$ od -a myfile.txt
$ cat -e myfile.txt
$ cat -v myfile.txt
$ hexdump -c myfile.txt
解释
查看新线的两种方法是自洽的,是新线要幺分开线,要幺终止行。如果将新线视为分隔符,则文件的最后一行之后将不会有Newline。有些程序在处理文件的最后一行时遇到了问题,如果该线路未被newline终止。另一方面,期望将Newline用作分离器的程序将把最终的Newline解释为启动新(空)线路。相反,如果新线被视为终结者,则所有包括最后一条在内的文本行都应被新线终止。如果文本文件中的最终字符序列不是新线,则文件的最后一行可能被认为是不适当或不完整的文本行,或者可以将文件视为不当截断。
在文本中,人类主要要使用实现Wrap功能的软件来读取,通常只需要单个折断,只有独立于下一个单词是否适合同一行,例如在段落之间,通常才需要存储一个newline字符并在垂直列表中。因此,在文字处理和大多数文本编辑器的逻辑中,Newline被用作段落中断,被称为“硬返回”,与“软返回”相反,这些返回是为实现Word包装而动态创建的,并且每个都可以改变显示实例。在许多应用程序中,存在一个称为“手动线路断裂”的单独的控制字符,以在单个段落内强制线断裂。硬返回的控制字符的字形通常是Pilcrow (¶),而对于手动线路,通常是托架返回箭头(↵)。
反向和部分线馈送
RI ( U +008D反向线馈, ISO/IEC 6429 8D,十进制141)用于将打印位置移回一条线(通过反向馈送纸张,或通过将显示光标移动一行),以便其他字符可以通过现有文本打印。这可能是为了使它们变得更大胆,或者添加下划线,罢工或其他角色(例如变音术) 。
同样,可以使用PLD ( U +008B局部线向前,十进制139)和PLU ( U +008C部分线向后,十进制140)可用于前进或反向文本打印位置以一定程度的垂直线间距(通常是一半,一半,一半) )。这些可以组合用于下标(通过前进,倒转)和上标(通过逆转然后前进),也可能对打印变音符号有用。