Tips - 行者无疆 始于足下 - 行走,思考,在路上

newline: line feed and carriage return

数学是神造科学,计算机是人造科学

所以在计算机的底层软件中,有着数不清的tricks,让人很无奈,但又无法避免。譬如Big-endian和Little-endian的问题,据说UNIX曾经移植到另外一台不同"endian"的机器上,结果系统启动显示的是NUXI而不是UNIX;再比如ASCII和Unicode,以及各种各样地方编码纠结的关系;连最简单的hello world,放到不同的平台上,生成的字符串也是不同的,考虑下面的程序:

#include <iostream>
using namespace std;
int main( int argc, char *argv[])
{
    cout << "Hello\nWorld";
}

这个程序如果在*nix平台下执行,生成的字符串的长度是11:

lox@lox-pad ~/tmp> clang++ main.cxx -o main
lox@lox-pad ~/tmp> ./main | wc -c
11
lox@lox-pad ~/tmp> ./main | od -c
0000000   H   e   l   l   o  \n   W   o   r   l   d
0000013
lox@lox-pad ~/tmp> 

但是如果放到windows上执行,那么程序生成的字符串的长度是12,字符串的值是"Hello\r\nWorld",so,what is '\r'?

细究起来,我们发现,一个小小的newline字符也有如此多的故事,或者说,历史包袱。Wikipedia里面给出了完整的解释。简单来讲,'\n'和'\r'的概念来源于早期的打字机,'\n'代表"line feed",表示打字机打完一整行后相对纸面向下移动一整行的距离,而'\r'则代表"carriage return",就是控制打字机重新回到一行的行首,'\r\n'连在一起用才会使得打字机移动到新的一行的行首开始工作。而在后来的OS设计中,由于在TTY终端并没有实体的打印机控制操作,所以在设计上将'\r\n'进行了简化处理,只是不同的OS采取的策略不一样。我们仅以Windows、Linux、Mac这三种最流行的系统来做说明。

  • Windows: '\r\n'
  • Linux: '\n'
  • Mac: '\r'

所以Linux和Mac上的多行文本文件用Windows的Notepad打开,常常会出现多行并做一整行的现象,而Windows上的文本文件用Linux上的Vim或者Emacs等editor来访问,往往会看到奇怪的'^M'字符,事实上这个'^M'并不是'^'+'M'的组合,它就是Windows中的'\r'。在Linux终端中你可以通过输入Ctrl+V Ctrl+M来获得'\r'这个输入。

那么,我们怎样去掉这写讨厌的影响心情和版面美感的'\r'呢?方法有很多,最简单的,安装dos2unix这个小软件,然后直接dos2unix filename即可,archlinux可以通过"pacman -S hd2u"来获取dos2unix,反过来也有unix2dos这样的命令。

除了dos2unix,利用Linux本身的shell工具,也可以达到目的,比如:

  • sed 's/^M//g' filename
  • sed 's/\r//g' filename
  • cat filename | tr -d '\r' > newfile
  • vim: %s/^M//g

最后需要注意的是,C语言的标准库针对这种情况做了专门的规定,并针对性的规定了text mode和binary mode,这种小的trick平时不需要注意,但是没准某一天就会冒出来拷打一下你的耐心。




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee