\ r和\ n在s命令中表示不同含义的原理是什么?


13

我们都知道,在搜索时\n是换行符,并且\r是回车符(^M),但是当替换\r是换行符时\n则是空字节(^@)。

这种不对称的根源是什么?鉴于这种行为是……至少可以说是怪异的(当您第一次出错时,它适得其反)我希望这是有一些奇怪的历史原因。

(顺便说一下,是否有某种方法可以“修复”此行为并获得更直观的效果?)

Answers:


10

在最基本的层次上,搜索和替换部分之间已经存在不对称性,:substitute因为前者是正则表达式,后者是文本,并带有特定的附加转义序列。您对\n方法的直觉只是突出了这一点。

例如,请考虑\n在搜索中不匹配文字\n。它线(EOL)字节序列的末端,其可以是相匹配\r\r\n或只是\n取决于'fileformat'在缓冲液中。

至于为什么\r用来“插入EOL”的原因,背后还有一些历史。Vi无法处理文件中的NUL字节。Vim通过在内部用NL字节替换NUL字节来改善了这一点(因为C字符串是NUL分隔的)。

该实现细节泄漏到了行为中,:substitute因为\n在替换中,它只是简单地插入到该行的内部表示中,该内部表示用于指示NUL字节。 \r插入一个EOL,将内部行一分为二。Vim实际上并不将EOL字节存储在内存中,而是在读取/写入缓冲区时对它们进行反序列化。

现在,如果不破坏许多用户的脚本和肌肉记忆就无法对其进行更改。幸运的是,它记录在中:help sub-replace-special


6

NUL字节是在C语言的字符串终止子,并且由于这个原因Vim使用该约定,在手册中所描述:h NL-used-for-Nul

文件中的<Nul>字符作为<NL>存储在内存中。在显示屏中,它们显示为“ ^ @”。读写文件时完成翻译。要将<Nul>与搜索模式匹配,您只需输入CTRL- @或“ CTRL-V 000”。这可能正是您所期望的。内部字符在搜索模式中被替换为<NL>。与众不同的是,键入CTRL-V CTRL-J还会插入<NL>,因此也会在文件中搜索<Nul>。{Vi根本无法处理文件中的<Nul>个字符}

该约定已溢出到:s/.../.../命令,但没有溢出到substitute()函数。 \r\n替换字符串中substitute()的呼叫保持其原有的意义。

我认为这两种行为都没有更深层次的原因。Vim只是从原始版本有机地演变而来vi。从来没有什么大的蓝图,功能只是相互叠加,而很少花费精力使它们井井有条。


0

其他Vi克隆不支持\r\n替代(以真实的反斜杠和字母表示),但是real ^MCTRL-V Enter)的行为是将行为分为两行,这是标准行为

repl中输入<carriage-return> (在ex模式下需要转义<backslash>,在open或vi模式下需要转义<control> -V )应在该点分割行,在编辑缓冲区中创建新行。<carriage-return>应该被丢弃。

在Unix History档案中,它出现的BSD ex / vi的第一个版本是4.1cBSD(@(#)ex_re.c 7.2 10/16/81,并且在4BSD中不存在(@(#)ex_re.c 6.2 10/23/80)[档案中不存在4.1a和4.1b]。

相关代码为:

/* ^V <return> from vi to split lines */
if (c == '\r')
    c = '\n';

新闻文件中也提到了这一点:

现在可以通过在rhs中使用^ V <return>来用vi中的替换命令分割行。这照顾了使用ex命令模式的最后一个很好的理由。

以前在ex命令模式下支持的行为是反斜杠输入(即反斜杠后跟真实的换行符)以插入换行符。


0

不对称性的起源可以追溯到计算历史中。

精简版:

<CR> & <LF>  (Carriage-Return and Linefeed) 
== 
\r & \n

较长的版本:
第一个屏幕基本上是电传打字机(TTY)的数字版本,并使用控制代码来产生与打印机相似的行为。回车将光标(或打印头)移至开始列。换行前进到下一行(在屏幕上),并将纸张向前一行送进。

对于打印机,您必须进行配对,<CR><LF>否则输出将看起来不正确。在早期的屏幕上,问题仍然存在。

DOS(和之后的sorta-Windows)遵循旧标准,并使用保存文本<CRLF>

* NIX文本(大多数vi用户熟悉)仅<LF>用于提高效率。

要在Windows中进行测试,请使用Word / Wordpad并保存几行文本“作为类型:文本-MS-DOS格式”。然后在记事本中打开相同的文件。它看起来应该很正常。然后在Word / Wordpad中将“类型”保存为相同的文件:“文本”。记事本将忽略所有换行符并一起运行这些行。[记事本的文本格式默认为\r\n组合,而Word / Wordpad默认为\n。]

\ r是等效的代码 <CR>

\ n等于 <LF>

根据我(非常有限的)使用vi的经验,它将尝试<CRLF>从DOS文本编辑器中“修复”该组合。vi最后删除了一个字符,替换为<NUL>。我停止使用vi的很大一部分原因。


2
虽然所有的信息很有趣,它只是告诉为什么\r<CR>\n<LF>。它没有解决实际的问题,即为什么在不同的上下文中\n\r表现不同
Tumbler41年

谢谢!:-)当您回复时,我正在更改它。(在最后一段中添加。)
罗宾(Robin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.