在Emacs中隐藏^M

60
有时我需要阅读具有 ^M (control-M) 行结尾的日志文件。我可以进行全局替换以摆脱它们,但随后会记录更多内容到日志文件中,它们当然会再次出现。
设置Unix样式或dos样式的行尾编码似乎没有什么区别(但Unix样式是我的默认设置)。我使用未决定-(unix|dos) 编码系统。
我正在使用 Windows 操作系统,阅读由 log4net 创建的日志文件(尽管 log4net 显然不是这种烦恼的唯一来源)。

1
不幸的是,set-buffer-file-encoding-system并不能解决这个问题。缓冲区打开时模式行显示为UNIX。使用C-x RET f UNIX RET只会将缓冲区标记为已修改,而无法隐藏令人讨厌的^M字符。 - Russell
GNUS 中的电子邮件是另一个可能遇到混合行尾编码缓冲区的地方。例如,如果从以 Windows 为中心的机构(如 Outlook)发送,则标题信息将获得 Unix 的行尾编码。 - Brady Trainor
12个回答

82
(defun remove-dos-eol ()
  "Do not show ^M in files containing mixed UNIX and DOS line endings."
  (interactive)
  (setq buffer-display-table (make-display-table))
  (aset buffer-display-table ?\^M []))

这是Johan Bockgård提出的解决方案,我在这里发现了它


6
如果您希望此功能几乎始终运行,请将以下内容添加到您的.emacs文件中(我花了一些时间才找到):(add-hook 'text-mode-hook 'remove-dos-eol) - Henrik
2
多年来我一直忍受着^M的煎熬。谢谢。 - EoghanM
@Henrik,我知道你的评论已经两年了,但是我无法让我的.emacs文件自动调用这个函数。除了文本模式之外,还有其他模式吗? - Russell
1
@Russell,C-h mdescribe-mode)有帮助吗? - Brady Trainor
这对我有用。我还通过向magit-diff-mode-hook添加一个附加项扩展了@Henrik的解决方案。理智再次统治 :-) - Philip Daniels

19

现代版本的emacs可以处理UNIX和DOS行尾符,所以当文件中出现^M时,这意味着文件中混合了两者。当存在混合时,emacs默认为UNIX模式,因此^M是可见的。真正的解决方法是修复创建文件的程序,使其使用一致的行尾符。


5
Emacs 错了,真正的解决方法是修复 Emacs。例如,git 会创建冲突文件,在“控制”行(比如以<<<<<<<开头的行)中不包含^M。对于 git 忽略文件的任何行结尾是完全有效的,因为控制行是“元数据”。 - EoghanM
2
这个答案解释了emacs的行为,但没有回答问题。原帖想要不看到CR (^M)字符,尽管它们仍然存在。 - Stéphane Gourichon

7

有什么问题吗?

C-x RET c dos RET C-x C-f FILENAME RET

我创建了一个文件,有两行内容,第二行有一个换行符。Emacs会以Unix编码打开该文件,切换编码系统无效。然而,上面的universal-coding-system-argument可以解决问题。


5
略微修改已打开的文件:C-x RET c dos RET M-x revert-buffer RET - Shelvacu

5

我相信你可以使用以下方法将文件的行编码系统更改为Unix格式:

C-x RET f UNIX RET

如果您这样做,模式行应该会添加单词“(Unix)”,所有那些^M都会消失。

不太有帮助,我认为。set-buffer-file-coding-system 似乎会改变编辑文件的实际内容。 - hillu
指定编码系统为 unix 对我没有起作用 -- 但是指定为 dos 后(在我恢复缓冲区之后)就可以了。 - John H.
@JohnH. - 我最近看到这种情况出现在一个文本文件中,因为它同时包含两种类型的行结束符。 Emacs 只能选择其中一种,而使用另一种结束符的行看起来很奇怪。通常最好选择你想要的那个,并修复有问题的行结束符。(例如:使用鼠标将 ^M 放入 kill 缓存区,然后使用 M-x query-replace 将其替换为空字符串) - T.E.D.

4
如果您想查看日志文件,只需隐藏^M而不实际替换它们,您可以使用Drew Adam的highlight extension来实现。
您可以编写elisp代码或制作键盘宏来执行以下操作。
select the whole buffer
hlt-highlight-regexp-region
C-q C-M
hlt-hide-default-face

这将首先突出显示^M,然后隐藏它们。如果您想要它们回来,请使用“hlt-show-default-face”。

谢谢你的插头,Justin。我在下面添加了另一个(不同的)解决方案。有多种方法可以达到同样的目的... - Drew

3

Edric的回答应该得到更多关注。Johan Bockgård的解决方案确实解决了发帖人的投诉,因为它使^M不可见,但这只是掩盖了根本问题,并鼓励进一步混合Unix和DOS换行符。

正确的解决方案是全局做一个M-x replace-regexp操作,将所有行结束符转换为DOS(或Unix,视情况而定)。然后关闭并重新打开文件(不确定M-x revert-buffer是否足够),^M要么全部都不可见,要么全部被删除。


3
M-x replace-string C-q C-m RET(来自http://lists.netisland.net/archives/plug/plug-1999-06/msg00365.html) - Robert Calhoun

2

将以下代码放入你的.emacs文件中:

(defun dos2unix ()
  "Replace DOS eolns CR LF with Unix eolns CR"
  (interactive)
    (goto-char (point-min))
      (while (search-forward "\r" nil t) (replace-match "")))

现在你可以简单地调用dos2unix来删除所有的^M字符。

2
您可以更改Control-M(^M)字符的显示表项,使其可显示为空格甚至完全消失(虚无)。请参见库pp-c-l.elPretty Control-L)中的代码,以获得灵感。它以任意方式显示^L字符。

编辑:糟糕,我刚注意到@binOr已经提到了这种方法。


1
如果你在Gnus中收到的邮件中遇到了^M,你可以使用W c(清洗回车符)来处理。
(setq gnus-treat-strip-cr t)

0

sudeepdino008的答案对我没有用(我无法在他的答案上评论,所以我不得不添加自己的答案)。

我使用以下代码成功解决了问题:

(defun dos2unix ()
  "Replace DOS eolns CR LF with Unix eolns CR"
  (interactive)
    (goto-char (point-min))
      (while (search-forward (string ?\C-m) nil t) (replace-match "")))

将来在人名前使用“@”符号:@RMK - Czipperz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接