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

这的起源是什么不对称?鉴于这种行为是...至少可以说是怪异的(当您第一次遇到错误时,它适得其反)我希望有一些奇怪的历史原因。
(顺便说一句,有什么方法可以“修复”此行为并获得更直观的提示?)

#1 楼

在最基本的层次上,: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中。

#2 楼

NUL字节是C中的字符串终止符,因此,Vim使用此约定,如:h NL-used-for-Nul手册中所述:文件中的


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


该约定已扩展到:s/.../.../命令,而不是substitute()函数。 \r调用中替换字符串中的\nsubstitute()保留了其原始含义。

我认为这两种行为都不存在更深层次的原因。 Vim只是从原始vi进行了有机演变。从来没有什么大的蓝图,功能只是相互叠放在一起,而只需花费很少的精力就可以使它们井井有条。

#3 楼

其他Vi克隆不支持替换\r\n(作为真实的反斜杠和字母),但是真实的^M(CTRL-V Enter)的行为是将行分为两行是标准行为:


在repl中输入(在ex模式下需要转义,在open或vi模式下需要转义 -V)将在该点分割行,从而创建编辑缓冲区中的新行。 应该被丢弃。


在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 来用vi中的替换命令来分割行。使用ex命令模式的原因。

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

#4 楼

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

简短版本:

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


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

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

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

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

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

\ r是<CR>的等效代码

\ n是<LF>的等效代码

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

评论


尽管您所有的信息都很有趣,但是它仅说明了为什么\ r是而\ n是。它没有解决\ n \ r为什么在不同上下文中表现不同的实际问题。

– Tumbler41
16年8月29日在19:52

谢谢! :-)当您回复时,我正在更改它。 (在最后一段中添加。)

–罗宾
16年8月29日在19:57