如何在 Vim 中用换行符替换字符

我想替换每个,在由新线当前文件:

:%s/,/\n/g

但它会插入看起来像^@而不是实际的换行符。该文件不在 DOS 模式下或其他任何状态。

我该怎么办?

如果您像我一样好奇,请查看问题, 为什么 \ ra newline for Vim?也一样

答案

使用\r代替\n

\n替换会在文本中插入一个空字符。要获取换行符,请使用\r搜索换行符时,您仍将使用\n 。这种不对称性是由于\n\r 所做的事情略有不同

\n匹配行尾(换行符),而\r匹配回车符。另一方面,在替换中, \n插入一个空字符,而\r插入一个换行符(更准确地说,它被视为输入 )。这是一个小的非交互式示例,使用 Vim 命令行功能进行了说明(换句话说,您可以将以下内容复制并粘贴到终端中以运行它)。 xxd显示了结果文件的xxd

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a                                bar.
After:
0000000: 000a 720a                                ..r.

换句话说, \n已将字节 0x00 插入文本; \r插入了字节 0x0a。

这是窍门:

首先,设置 Vi(m)会话以允许使用特殊字符(即:换行符)进行模式匹配。可能值得将此行放入. vimrc 或. exrc 文件中:

:set magic

接下来,执行:

:s/,/,^M/g

要获取^M字符,请输入Ctrl + V,然后按 Enter 。在 Windows 下, 按 Ctrl + Q ,然后输入 。我唯一能记住这些的方法是记住它们的意义:

答: 用来代表换行符的最糟糕的控制字符是什么?

B: q (因为通常表示 “退出”)或v是因为错误输入Ctrl + C并杀死编辑器非常容易。

答: 可以。

在语法s/foo/bar ,根据上下文, \r\n具有不同的含义。


短:

对于foo

\ n = 换行符(在 Linux / Mac 上为 LF,在 Windows 上为 CR + LF)
\ r = 回车(CR)

对于bar

\ r = 是换行符
\ n = 空字节。

更长(使用 ASCII 数字):

NUL = 0x00 = 0 = Ctrl + @
LF = 0x0A = 10 = Ctrl + J
CR = 0x0D = 13 = Ctrl + M

这是ASCII 控制字符的列表。通过Ctrl + VCtrl + --- key --- 将它们插入 Vim。

在 Bash 或其他 Unix / Linux shell 中,只需键入Ctrl + --- key ---

在 Bash 中尝试Ctrl + M 。尽管 Linux 系统使用换行符进行行定界,但 Shell 意识到了它的含义与按Enter相同。

要在 bash 中插入文字,也可以在它们前面加上Ctrl + V

在 Bash 中尝试:

echo ^[[33;1mcolored.^[[0mnot colored.

这使用ANSI 转义序列 。通过Ctrl + VEsc插入两个^[ 's。

您也可以尝试按 Ctrl + VCtrl + MEnter ,这将为您提供:

bash: $'\r': command not found

还记得上面的\r吗? :>

ASCII 控制字符列表与完整的ASCII 符号表不同 ,在于可以在其中找到通过Ctrl键(haha)插入到控制台 / 伪终端 / Vim 中的控制字符。

而在 C 语言和大多数其他语言中,通常使用八进制代码表示这些 “字符”。

如果您真的想知道所有这些信息来自何处: TTY 变得神秘 。这是您会遇到的关于此主题的最佳链接,但请注意:有龙。


TL; DR

通常foo = \nbar = \r

您需要使用:

:%s/,/^M/g

要获取^M字符,请按Ctrl + v,然后按Enter

\r可以为您完成这里的工作。

在 Windows 上的 Vim 中,使用Ctrl + Q代替Ctrl + V。

Eclipse 中^M字符可以嵌入到一行中,并且您希望将它们转换为换行符。

:s/\r/\r/g

这是我思考方式的最佳答案,但在表中会更好:

为什么 \ ra newline for Vim?

因此,改写:

您需要使用\r在正则表达式替换中使用换行符(ASCII 0x0A ,Unix 换行符),但这是该替换所特有的 - 通常,您应该继续期望使用\n进行换行,而使用\r进行换行返回。

这是因为 Vim 在替换中使用\n表示 NIL 字符(ASCII 0x00 )。您可能希望 NIL 改为\0 ,将\n释放给它通常用于换行,但是\0在正则表达式替换中已经具有含义,因此将其转移到\n 。因此,接下来还要将换行符从\n移到\r (在正则表达式模式中,它是回车符 ASCII 0x0D )。

Character                | ASCII code | C representation | Regex match | Regex replacement
-------------------------+------------+------------------+-------------+------------------------
nil                      | 0x00       | \0               | \0          | \n
line feed (Unix newline) | 0x0a       | \n               | \n          | \r
carriage return          | 0x0d       | \r               | \r          | <unknown>

注意: ^M (在 Linux 上为Ctrl + V Ctrl + M )用于正则表达式替换时会插入换行符,而不是像其他人建议的那样返回回车符(我刚刚尝试过)。

还要注意,Vim 在基于文件格式设置保存到文件时会转换换行符,这可能会引起混乱。

但是如果必须替换,则可以进行以下操作:

:%s/\n/\r\|\-\r/g

在上面,下一行替换为下一行,然后|-再次替换为新行。这在 Wiki 表中使用。

如果文本如下:

line1
line2
line3

改为

line1
|-
line2
|-
line3

如果您需要对整个文件执行此操作,还建议我可以从命令行尝试:

sed 's/\\n/\n/g' file > newfile