2009年4月7日星期二

字符编码详解及由来(ANSI,UNICODE,UTF-8,GBK)

一直对字符的各种编码方式懵懵懂懂,什么ANSI、UNICODE、UTF-8、GB2312、GBK、DBCS、UCS……是不是看的很晕,假如您细细的阅读本文你一定可以清晰的理解他们。Let's go!
很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物。他们看到8个开关状态是好的,于是他们把这称为"字节"。

再后来,他们又做了一些可以处理这些字节的机器,机器开动了,可以用字节来组合出很多状态,状态开始变来变去。他们看到这样是好的,于是它们就这机器称为"计算机"。
开始计算机只在美国用。八位的字节一共可以组合出256(2的8次方)种不同的状态。
他们把其中的编号从0开始的32种状态分别规定了特殊的用途,一但终端、打印机遇上约定好的这些字节被传过来时,就要做一些约定的动作。遇上00x10,终端就换行,遇上0x07, 终端就向人们嘟嘟叫,例如遇上0x1b,打印机就打印反白的字,或者终端就用彩色显示字母。他们看到这样很好,于是就把这些0x20以下的字节状态称为"控制码"。
他们又把所有的空格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号,这样计算机就可以用不同字节来存储英语的文字了。大家看到这样,都感觉很好,于是大家都把这个方案叫做ANSI 的"Ascii"编码(American Standard Code for Information Interchange,美国信息互换标准代码)。当时世界上所有的计算机都用同样的ASCII方案来保存英文文字。
后来,就像建造巴比伦塔一样,世界各地的都开始使用计算机,但是很多国家用的不是英文,他们的字母里有许多是ASCII里没有的,为了可以在计算机保存他们的文字,他们决定采用127号之后的空位来表示这些新的字母、符号,还加入了很多画表格时需要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。从128到255这一页的字符集被称"扩展字符集"。从此之后,贪婪的人类再没有新的状态可以用了,美帝国主义可能没有想到还有第三世界国家的人们也希望可以用到计算机吧!

等中国人们得到计算机时,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要保存呢。但是这难不倒智慧的中国人民,我们不客气地把那些127号之后的奇异符号们直接取消掉,规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
中国人民看到这样很不错,于是就把这种汉字方案叫做 "GB2312"。GB2312是对 ASCII 的中文扩展。
但是中国的汉字太多了,我们很快就就发现有许多人的人名没有办法在这里打出来,特别是某些很会麻烦别人的国家领导人。于是我们不得不继续把GB2312 没有用到的码位找出来老实不客气地用上。
后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为GBK 标准,GBK 包括了 GB2312的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。
后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK扩成了GB18030。从此之后,中华民族的文化就可以在计算机时代中传承了。
中国的程序员们看到这一系列汉字编码的标准是好的,于是通称他们叫做"DBCS"(Double Byte Charecter Set双字节字符集)。在DBCS系列标准里,最大的特点是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里,因此他们写的程序为了支持中文处理,必须要注意字串里的每一个字节的值,如果这个值是大于127的,那么就认为一个双字节字符集里的字符出现了。那时候凡是受过加持,会编程的计算机僧侣们都要每天念下面这个咒语数百遍:

"一个汉字算两个英文字符!一个汉字算两个英文字符……"
因为当时各个国家都像中国这样搞出一套自己的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码,连大陆和台湾这样只相隔了150海里,使用着同一种语言的兄弟地区,也分别采用了不同的DBCS编码方案——当时的中国人想让电脑显示汉字,就必须装上一个"汉字系统",专门用来处理汉字的显示、输入的问题,但是那个台湾的愚昧封建人士写的算命程序就必须加装另一套支持BIG5编码的什么"倚天汉字系统"才可以用,装错了字符系统,显示就会乱了套!这怎么办?而且世界民族之林中还有那些一时用不上电脑的穷苦人民,他们的文字又怎么办?

真是计算机的巴比伦塔命题啊!
正在这时,大天使加百列及时出现了——一个叫ISO(国际标谁化组织)的国际组织决定着手解决这个问题。他们采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号的编码!他们打算叫它"Universal Multiple-Octet Coded Character Set",简称 UCS, 俗称 "UNICODE"。

UNICODE开始制订时,计算机的存储器容量极大地发展了,空间再也不成为问题了。于是 ISO
就直接规定必须用两个字节,也就是16位来统一表示所有的字符,对于ascii里的那些"半角"字符,UNICODE包持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。由于"半角"英文符号只需要用到低8位,所以其高8位永远是0,因此这种大气的方案在保存英文文本时会多浪费一倍的空间。

这时候,从旧社会里走过来的程序员开始发现一个奇怪的现象:他们的strlen函数靠不住了,一个汉字不再是相当于两个字符了,而是一个!是的,从UNICODE开始,无论是半角的英文字母,还是全角的汉字,它们都是统一的"一个字符"!同时,也都是统一的"两个字节",请注意"字符"和"字节"两个术语的不同,"字节"是一个8位的物理存贮单元,而"字符"则是一个文化相关的符号。在UNICODE中,一个字符就是两个字节。一个汉字算两个英文字符的时代已经快过去了。
从前多种字符集存在时,那些做多语言软件的公司遇上过很大麻烦,他们为了在不同的国家销售同一套软件,就不得不在区域化软件时也加持那个双字节字符集咒语,不仅要处处小心不要搞错,还要把软件中的文字在不同的字符集中转来转去。UNICODE对于他们来说是一个很好的一揽子解决方案,于是从 Windows NT 开始,MS趁机把它们的操作系统改了一遍,把所有的核心代码都改成了用 UNICODE方式工作的版本,从这时开始,WINDOWS系统终于无需要加装各种本土语言系统,就可以显示全世界上所有文化的字符了。
但是,UNICODE 在制订时没有考虑与任何一种现有的编码方案保持兼容,这使得GBK 与UNICODE在汉字的内码编排上完全是不一样的,没有一种简单的算术方法可以把文本内容从UNICODE编码和另一种编码进行转换,这种转换必须通过查表来进行。
如前所述,UNICODE是用两个字节来表示为一个字符,他总共可以组合出65535不同的字符,这大概已经可以覆盖世界上所有文化的符号。如果还不够也没有关系,ISO已经准备了UCS-4方案,说简单了就是四个字节来表示一个字符,这样我们就可以组合出21亿个不同的字符出来(最高位有其他用途),这大概可以用到银河联邦成立那一天吧!
UNICODE 来到时,一起到来的还有计算机网络的兴起,UNICODE如何在网络上传输也是一个必须考虑的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8就是每次8个位传输数据,而UTF16就是每次16个位,只不过为了传输时的可靠性,从UNICODE到UTF时并不是直接的对应,而是要过一些算法和规则来转换。

受到过网络编程加持的计算机僧侣们都知道,在网络里传递信息时有一个很重要的问题,就是对于数据高低位的解读方式,一些计算机是采用低位先发送的方法,例如我们PC机采用的INTEL架构,而另一些是采用高位先发送的方式,在网络中交换数据时,为了核对双方对于高低位的认识是否是一致的,采用了一种很简便的方法,就是在文本流的开始时向对方发送一个标志符——如果之后的文本是高位在位,那就发送"FEFF",反之,则发送"FFFE"。不信你可以用二进制方式打开一个UTF-X格式的文件,看看开头两个字节是不是这两个字节?
讲到这里,我们再顺便说说一个很著名的奇怪现象:当你在 windows的记事本里新建一个文件,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是几个乱码!呵呵,有人说这就是联通之所以拼不过移动的原因。

其实这是因为GB2312编码与UTF8编码产生了编码冲撞的原因。
从网上引来一段从UNICODE到UTF8的转换规则:
Unicode                        UTF-8
0000 - 007F                   0xxxxxxx
0080 - 07FF                   110xxxxx 10xxxxxx
0800 - FFFF                   1110xxxx 10xxxxxx 10xxxxxx
例如"汉"字的Unicode编码是6C49。6C49在0800-FFFF之间,所以要用3字节模板:1110xxxx
10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 1100 0100 1001,将这个比特流按三字节模板的分段方法分为0110 110001 001001,依次代替模板中的x,得到:1110-0110 10-110001 10-001001,即E6 B189,这就是其UTF8的编码。
而当你新建一个文本文件时,记事本的编码默认是ANSI,如果你在ANSI的编码输入汉字,那么他实际就是GB系列的编码方式,在这种编码下,"联通"的内码是:
c1 1100 0001
aa 1010 1010
cd 1100 1101
a8 1010 1000
注意到了吗?第一二个字节、第三四个字节的起始部分的都是"110"和"10",正好与UTF8规则里的两字节模板是一致的,于是再次打开记事本时,记事本就误认为这是一个UTF8编码的文件,让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了"0000 0000 0110 1010",不好意思,这是UNICODE的006A,也就是小写的字母"j",而之后的两字节用UTF8解码之后是0368,这个字符什么也不是。这就是只有"联通"两个字的文件没有办法在记事本里正常显示的原因。

而如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,而会用ANSI的方式解读之,这时乱码又不出现了。
好了,终于可以回答NICO的问题了,在数据库里,有n前缀的字串类型就是UNICODE类型,这种类型中,固定用两个字节来表示一个字符,无论这个字符是汉字还是英文字母,或是别的什么。

如果你要测试"abc汉字"这个串的长度,在没有n前缀的数据类型里,这个字串是7个字符的长度,因为一个汉字相当于两个字符。而在有n前缀的数据类型里,同样的测试串长度的函数将会告诉你是5个字符,因为一个汉字就是一个字符。

HelloWorld in autoconf & automake

写个autoconf和automake的HelloWorld先,以后再慢慢添加些常用宏的含义。
ok,让我们从hello.c开始
#include <stdio.h>
main()
{
printf("Howdy world!
");
}
当然你可以像下面这样简单的编译这个程序
% gcc hello.c -o hello
% hello
让我们看看使用autoconf和automake的编译方法,首先创建下面两个文件
`Makefile.am'
bin_PROGRAMS = hello
hello_SOURCES = hello.c
`configure.in'
AC_INIT(hello.c)
AM_INIT_AUTOMAKE(hello,0.1)
AC_PROG_CC
AC_PROG_INSTALL
AC_OUTPUT(Makefile)
运行 `autoconf':
% aclocal
% autoconf
上面这一步将产生我们熟悉的`configure'脚本。接下来运行 `automake':
% automake -a
required file "./install-sh" not found; installing
required file "./mkinstalldirs" not found; installing
required file "./missing" not found; installing
required file "./INSTALL" not found; installing
required file "./NEWS" not found
required file "./README" not found
required file "./COPYING" not found; installing
required file "./AUTHORS" not found
required file "./ChangeLog" not found
'-a' 的意思是'add missing standard files to
package',第一次运行automake它会帮我们产生一些标准的文件,这些文件都是为了符合GNU编码标准,但也会出现一些文件找不到的错误,这些文件需要我们自己创建:
% touch NEWS README AUTHORS ChangeLog
再跑一下automake:
% automake -a
这时就会产生`Makefile.in'
现在所有的任务都完成,可以打包分发了,使用方法地球人都知道:
% ./configure
% make
% ./hello

zenity,小巧方便的对话框工具

写shell的时候需要大量的echo一些东东出来看,从来不敢想弹出个对话框跟用户交互,有了zenity这个小工具这个想法很容易就实现了。

首先来个进度条的
把这句方到shell命令行执行一下
declare -i i=1; while [ $i != 101 ]; do usleep 10000; echo $i; i=$i+1;
done | zenity --progress
是不是超级酷
进度条启动以后会读取标准输入
根据标准输入的数字就可以动态显示进度条了


最常用的还有--entry、--file-selection、--question等
一般来说只要用户选择了'确定'
那么zenity的返回值就是0
否则就是非零
这个返回值对脚本的判断很有用
zenty还可以接收用户输入并返回给shell
例如
uname=`zenity --entry --text="what's your name?"`; if [ $? == 0 ]; then
echo $uname; fi #如果用户输入了名字就打印他的名字,否则不打印

其他的还有很多
敲zenity --help可以得到这些输出
--calendar Display calendar dialog
--entry Display text entry dialog
--error Display error dialog
--info Display info dialog
--file-selection Display file selection dialog
--list Display list dialog
--notification Display notification
--progress Display progress indication dialog
--question Display question dialog
--warning Display warning dialog
--text-info Display text information dialog
--display=DISPLAY X display to use

2009年4月6日星期一

调整内核参数,改善网络体验

通常,Linux内核和基于其的各种发行版,对于网络方面的设置都只提供了相当保守的参数,事实上,我们可以通过/proc文件系统或者使用sysctl程序来调节这些参数。后者要更加方便一些,因为这个工具是读取和改写
/etc/sysctl.conf中的内容,这样你在重新启动后,所有设置都不会丢失。

下面就是可能提升你网络性能的参数摘录:


net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_syncookies = 1
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

注意,并不是说让你去用这些东西来覆盖文件中的内容,而是去补充它们,因为本来是不存在这些参数设置的。下面,就来介绍一下这些参数的意思。

第一个参数是用于打开TCP窗口的调节的,它允许客户端通过使能TCP包中额外的bit位来增加窗口长度,以达到更高的速度进行数据下载的效果。

第二个参数是用于打开TCP SYN
cookies功能,该功能可以防止部分SYN洪水攻击,以免不断的链接请求会极大消耗服务器的资源,实际上就是降低syn的重试次数。

接下来的四个选项则是增加TCP的发送和接受缓冲。这样,应用程序能够更快传输数据,同时也就有更多的时间来处理其他请求。这些参数同时还提升了当前比较忙碌的客户端发送数据到服务器端的能力。

在把这些参数选项添加到/etc/sysctl.conf后,你需要通过命令

# sysctl -p /etc/sysctl.conf

来让它们生效,不用重启机器哦。想知道它们是不是真的起作用了呢?用命令

# sysctl -a

它会列出所有选项以及相关值,sysctl.conf文件允许你配置并保存新的默认值,你从sysctl
-a的结果中看见的值就是新的当前默认有效的值。如果你觉得太多了,看得眼花,可以通过命令

# sysctl -q net.ipv4.tcp_window_scaling

来查看某个特定的选项。当然,你也可以通过命令

# sysctl -w net.ipv4.tcp_window_scaling=1

来临时设置某个选项的值,但别忘了是临时哦,一旦重新启动设置就会丢失。所以一般这个命令是用于测试的。

2009年4月5日星期日

救火沉思录--关于项目最后阶段的思考

原帖:http://blog.csdn.net/absurd/archive/2005/12/13/551588.aspx
作者联系方式:李先静 <xianjimli at hotmail dot com>

这几个月来,大部分业余时间,都花在阅读软件工程和编译原理方面的书籍上了。软件工程方面的书,包括软件需求、风险管理、敏捷建模,系统设计,软件项目管理,还有一些类似于的沉思录书籍等。

在这些书中,都只是讲了如何让项目健康发展,最后成功的提交一个产品。尽管它们都是从不同的角度,用不同的方法去完成同样的事。但它们几乎都支持这样的观点:计划+修正计划(不但设计是迭代的,计划也是迭代的)。用其中一个作者的话说,伤害你的,不是那些你没有考虑完整的,而是你根本没去考虑的事情。

然而,几乎没有一本书里,讲到关于消防队的事,唉,真是奇怪,老外声称有超过50%的项目是失败的,那么在他们的项目中,失火也是常事,为什么就不谈谈救火的招数呢?难道他们也相信,不叫出魔鬼的名字,魔鬼就不会找上门来吗?

唯一的解释就是,救火太难了,可能老外的救火能力远不如我们,他们干脆就不谈了。我在上一个项目中牺牲惨重,巨大的压力之下,和女友分手,精神上和身体上都受到极大的伤害,当然,我不是那个项目唯一的牺牲品,很多同事,他们很优秀,也一样的无助。之后,我一直在想,既然有50%的项目会失火,那么救火能力和计划能力至少是等同重要了。我苦苦的思索,回忆上次的经历,查找相关资料,然而收获甚微。

救火的银弹也许永远不会出现,我把自己一些经验写出来,或许对大家有点帮助,如果能达到抛砖引玉的效果那是更好了:

1. 在FIX
BUG过程中,持续进行重构。在设计时没有做好,重做是不太可能的了,但绝望也是没有意义的,我们只能想法去改进它。利用前人一些经验,持续进行重构,每FIX一个BUG,我们让代码更好一点,而不是更坏一点,FIX了一个BUG,代码中就少了一个BUG,而不是引更多的BUG。在实际上,重构最大的困难是没有完整的自动测试程序和测试用例,这使得我们根本不敢去改动代码,或者为了让改动最小,采取一些折中的方法,这都使得代码不断的变臭。在这种情况下,建议是建立自动测试,然后不断完善测试用例,我觉得建立自动测试任何时候都不晚。如果建立自动测试确实比较困难,那就列出所有的测试用例,然后手工测试。这时候,工程师的工作就是:重构à测试àFIX
BUGà测试。有人说,我没有时间去重构,没有时间去测试。呵,这会使我想到,一个人围绕着一个小圆圈拼命的奔跑,累得半死的时候,发现在原地,他还在说,我没有时间去看清方向。

2.
关注常用功能。在项目的最后阶段,千万不要被QA牵着走,他们发现一个BUG,我们就FIX它。FIX一个BUG当然好,但是FIX
BUG不是免费的,要不但要成本,还有潜在的风险。编译的优化原理是基于:20%的代码花了80%的时间。如果这个原理成立,可以推出:80%的用户实际上只使用20%的功能。QA并不是最终用户,QA和最终用户的不同在于:QA尽力去发现不常见的问题,而最终用户经常使用最常用的功能。这时候我们可以把自己想成最终用户,列出最常用的测试用例,如果不在这些测试用例中的情况,即使BUG的现象很严重,我们也要考虑一下再决定是否修改它。

3.
确定哪些BUG不改同样重要。这一点与2有一定的重复,为了强调有必要单独提出来。在软件需求分析时,分析师们都认为,要确定什么不在系统内和什么在系统内一样重要。程序员对于BUG态度,有时往往走两个极端:一种是老子就不改。一种QA怎么说我就怎么改。前者往往被看着工作态度不端正。而后者呢,却被视为好孩子。其实,在项目的最后阶段,后者未必正确,正如前面所说,FIX
BUG不是免费的。这时候建立一个仲裁委员会有必要的,确定哪些BUG不改是他们的职责之一。

4.
BUG分类,明确责任。以前接手别人一个模块,处于Pending状态的BUG已经有110多个了。要把每一个BUG都看一遍就要花几个小时,不看吧,每次改一个BUG时,总有只见树木不见森林的感觉。最初,我很努力的去修改BUG,进展还是甚微。后来我花了几天时间,仔细分析了所有BUG,把它们归纳几类:其它模块引起的BUG;
和其它模块的接口引起的BUG; 超出需求之外的BUG;
完全是本模块内部的BUG。然后把其它模块引起的BUG提交给相关人员,和相关人员确认因接口不统一引起的BUG,把超出需求之外的BUG提交给需求控制委员会,最后剩下本模块的BUG又根据引起BUG的原因分为几类。这样,这些BUG很快被FIX了。

5.
工程师应该积极寻求帮助。有什么自己解决不了问题,应该向知道的人请教,或者向上司寻求帮助,不要出于面子或者其它原因,而花费大量的时间。在项目的最后阶段,每一分钟都很宝贵,不要重新发明轮子,对于有共性的难题也应该由专人解决。

6.
项目经理应该把眼光放在全局上。项目经理应该更多的关注于全局的事务,不要学只想拿大红花的小学生。别只顾修改自己的BUG,你的BUG少,并不能说明你是个好项目经理,在项目失败时,你个人的BUG少,并不能真正减轻你的罪恶感。据说软件团队遵循水桶原则,最低的那块木板才是决定装多少水要素,而不是最高的那块。项目经理应该随时关注哪块是最低的,然后把它补起来,自己成为最高的那块是没有意义的。

7. Person Review以提高士气。呵,不知道有没有Person
Review这个术语,反正我觉得挺好的,在项目的最后阶段,士气是非常宝贵的东西,可以说得士气者得天下。在前一个公司,每周一,老板会把每个工程师叫到他的办公室,一起聊会儿,聊天内容不限,多半是问问你这边工作上存在什么问题,有什么看法,非常坦白的谈一会儿,最后会得到他的鼓励和赞扬,自己感觉这对提高士气很有帮助的,当然老板最好是个好的煽动者。

8. Bug Review。建立一个Bug Review小组,他们的主要责任是:
发现一些具有共性的BUG,确认哪些BUG需要FIX,哪个BUG不用FIX。有共性的BUG,让专人解决或者督促。不管一个BUG是要FIX还是不用FIX,都要注明足够的理由。

9.
加强QA和RD之间的合作。呵,根据遗传学和适者生存原理可以知道,在最后阶段,BUG的生命力极强,往往花费很长时间才能重现。加上自然语言本身具有的二义性和个人看问题的侧重点不同,QA可能忽略了RD让认为很重要的重现步骤,QA的BUG描述在RD眼中也可能迥然不同。在这个阶段,直接到现场和QA交流一下,可能会节省很多时间。同时也要尊重QA的劳动成果,这样他们才会更积极的配合。

10.
经验积累。每遇到一个BUG,想一想,它为什么会出现,为什么才出现,修改它后会有什么后果。把重要的记录下来,可能对自己和别人都有所启发,以减少犯同样错误的机会。

徐志摩陆小曼

七夕节是中国的情人节,就在牛郎织女相会的那天,1926年北京北海公园进行了一场人们议论了很久的婚事。新郎徐志摩,新娘陆小曼早已成了舆论的中心,婚礼上,徐志摩老师梁启超的祝词使得在场的所有人,除了他自己之外,都感到难堪。他不仅没有讲吉祥话,反而对新郎、新娘痛斥,切责他们不该把婚姻当成儿戏,最后说道:"祝你们这是最后一次结婚!"事后梁启超写信给他的女儿梁令娴,说道:"我昨天做了一件极不愿意做的事,就是去替徐志摩证婚。他的新妇是王赓的夫人。与志摩爱上才和王赓离婚,实在是不道德之极。志摩找到这样一个人做伴侣,怕将来痛苦会接踵而来。所以不惜声色俱厉地予以当头棒喝,盼能有所觉悟,免得将来把志摩弄死。我在结婚礼堂上大大地予以教训,新人及满堂宾客无不失色,此恐为中外古今未闻之婚礼也。"
  陆小曼是北京城里有名的交际花,她的父亲陆定原是财政部的赋税司司长,后来弃政从商,出任震华银行总经理,算得上是一位财神爷型的人物。陆家有的是钱,舍不得让宝贝女儿进学堂,便把需要的老师都请到家里,所以陆小曼虽然没有上过学,除中国文字颇具造诣外,英文、法文的口语笔译都流畅自然。在艺术方面,除写得一手绢秀的毛笔字外,国画、京戏、舞蹈样样都行。再加上她从小口齿伶俐,长得象个小仙女似的,便赢得了"绝代佳人"的美誉。
  陆小曼的第一个丈夫就是梁启超信中提到的王赓,曾留学美国普林斯顿大学,西点军校。与陆小曼结婚的时候,正任教北京大学。婚后不久,两人的生活方式与生活习惯便产生了差异。王赓办事认真负责,为准备授课经常埋头研究。陆小曼生性风流,三天两头到外头游乐。于是王赓认为陆小曼没有尽到一个妻子的责任,也没有守住妇道人家的本份;陆小曼则认为王赓不够体贴,喝过洋墨水的的人还如此古板。这时王赓留学美国时的好友,北京大学的同事徐志摩悄悄地介入进来。
  陆小曼是江苏武进人,徐志摩是浙江硖石人,比王赓小一岁,比陆小曼大六岁。曾入北京大学、美国克拉克大学、英国剑桥大学读书,生来绝顶聪明,后来拜在梁启超的门下。他的散文、新诗把中国古典文学和西方文学揉合在一起,深入浅出、华而不腻、媚而不俗。"五四"运动前夕,他提任《北京晨报》的副主编,后来又成立"新月书店",发行《新月杂志》。在新文化运动中推波助澜,他成了追求时髦的人崇拜的偶像。徐志摩卓尔不群、兴趣广泛、风流潇洒。他早就有了结发妻子张嘉玲,但在欧洲留学期间拼命追求林徽音。这样的人自然是陆小曼喜爱的。
  徐志摩是王赓的好朋友,渐渐地和陆小曼也就熟悉了。王赓一旦遇到事情多分不开身或是懒得出去的时候,便叫徐志摩陪着陆小曼外出游山玩水或钻进灯红酒绿的场合消遣。那时,徐志摩正处在失恋阶段,他拚命追求的林徽音瞧不起他,和梁启超的长子梁思成结婚了。于是便把满腹的柔情转移到陆小曼身上。恰好王赓受聘赴哈尔滨提任警察局长,陆小曼空闺独守、芳心寂寞。陆、徐二人就象A、B胶一样,越粘越紧。
  从传统道德讲,徐志摩追求陆小曼,算是对结发妻子张嘉鈖不忠,对朋友王赓不义。然而徐志摩向来是随兴而为、不拘绳墨,一旦"邂逅赏心,相倾怀抱",就顾不了身外之事了。陆家和徐家都认为他们是不孝子女,是丑闻,极力阻止。徐志摩、陆小曼认为:"真爱不是罪恶,在必需时未尝不可以付出生命的代价来争取,与烈士殉国、教徒殉道,同是一理。"


徐志摩向世人宣示:"我之甘冒世之不韪,乃求良心之安顿,人格之独立。在茫茫人海中,访我灵魂之伴侣,得之我幸,不得我命,如此而已!"两人在风气初开的潮流中,受到青年男女的怂恿、喝采,豪气干云地踏上"不思旧姻求新婚"的道路。像郁达夫就说:"志摩热情如火,小曼温柔如棉,两人碰在一起,自然会烧成一团,那里还顾得了伦教纲常,更无视于宗法家风。"
  这时王赓受了孙传芳的邀请到了南京,在五省联军总司令部内提任总参谋长的职务,位高权重。风闻妻子行为有异,以快刀斩乱麻的方式,写了一封快信给陆小曼声言:"如念夫妻之情,立刻南下团聚,倘若另有所属,决不加以拦阻。"几经周折,徐志摩与张嘉玲离了婚,王赓与陆小曼也办了分离的手续。王赓对陆小曼酸溜溜地说:"合得来是夫妻,合不来就分开,我自愿退让来成全你们,希望你能过得幸福。"
  在胡适、郁达夫等一批朋友的帮助下,徐志摩积极筹备婚礼。徐家和陆家的长辈对徐志摩、陆小曼的事情十分痛恨,是坚决不参加婚礼的。于是徐志摩的老师梁启超尽管也反对他们两人的结合,是一定要请到的。
在胡适等人一再相劝,好说歹说的情况下,梁启超终于答应参加婚礼。婚礼如期举行,梁启超说了前面提到的那段惊世骇俗的话,想不到竟灵验如神。婚后不久,陆小曼就提出要移居上海,说是要借十里洋场的五光十色,冲淡在北京积累下来的一身晦气。
  他们在福熙路四明村里筑起爱的窝巢,有一段时间两人过得十分甜蜜。第二年春天,暖风醉人、百花怒放。陆小曼终于按捺不住蠢蠢欲动的荡漾春心,开始故态复萌。才刚刚投身社交圈里,便立刻造成极大的轰动。上海是藏龙卧虎之地,多的是满清遗老、王孙贵胄、富商巨贾,以及有钱又有闲的世家子弟。于是有人请她吃饭;有人邀她跳舞;更有人出来怂恿她票戏义演。风头算是出足了,时间、精神与金钱都一齐赔了进去,陆小曼认为十分值得,徐志摩却暗暗叫苦不已。
  有一个叫翁端午的苏州人,家财丰厚、赋性风流、吃喝玩乐、不务正业、出手阔绰、挥霍无度,是雅歌集票房的台柱,更有一手推拿的医道本领。通过票戏与陆小曼相识,于是在陆小曼面前大献殷勤,两人常常搭挡演出获得满堂喝彩。有一次陆小曼演出大轴,唱做累人,曾经一度晕厥。翁端午施展他的推拿绝技,为陆小曼捏捏揉揉,居然解除了陆小曼的疲劳。于是陆小曼便常常要翁端午为她推拿,感到通体舒服,两人的关系渐入佳境。翁端午又教会陆小曼吃鸦片。这样翁端午在陆小曼身上一会儿上下其手,抚摸揉搓;一会儿又和陆小曼倚枕横陈,对灯吞云吐雾,连旁人都看不过去。然而徐志摩仍以赤子之心为娇妻辩护,他解释说:"夫妇的关系是爱,朋友的关系是情,罗襦半解、妙手摩挲,这是医病;芙蓉对枕,吐雾吞云,最多只能谈情,不能做爱。"
于是陆小曼得寸进尺,完全不把徐志摩放在眼里,当着徐志摩的面与翁端午出双人对,甚至做出亲妮的举动来。当年徐志摩所做的,如今翁端午做得似乎更彻底;当年王庚所难堪的情事,此时徐志摩也尝到了个中苦涩的滋味。真是报应,徐志摩现在是血淋淋地跌在人生现实的荆棘丛中。
  夫妻的感情出现了裂痕,陆小曼仍毫不在乎,昏天黑地地玩着。徐志摩为了供应妻子无底的挥霍,除了在上海教书写作赚钱以外,还风尘仆仆地远赴北京开源。时而上海、时而北京,两头奔忙。
  一九三一年十一月十七日,徐志摩从北京回到上海,晚上和几个朋友在家中聊天。陆小曼依然是很晚才回家,而且喝得醉眼朦胧。朋友们先后了,徐志摩窝了一肚子的火。
第二天,徐志摩耐心开导劝说陆小曼,陆小曼根本就听不进去,两人于是大吵一场。陆小曼正在烟榻上过鸦片烟瘾,突然发起小姐脾气,抓起烟灯就往徐志摩身上砸。虽然没有砸中徐志摩的脑袋,却贴着额角飞过,打掉了徐志摩的眼镜。
徐志摩彻底地绝望,悄然离家到了南京,十九日搭乘中国航空公司京平线的济南号飞机,飞往北平。飞到济南附近的党家庄,遇到漫天大雾,飞机误触开山山头,机毁人亡,徐志摩手脚烧成焦炭,死状极惨。
  徐志摩的死引起极大的震撼,朋友们纷纷从各地赶来,为他操持丧事,郁达夫撰写的挽联高挂灵堂:

       两卷新诗,廿年旧友,相逢同是天涯,只为佳人难再得;
       一声河满,几点齐烟,化鹤重归华表,应愁高处不胜寒。

  而灵堂中最显眼、最感人的挽联还是徐志摩的原配夫人张嘉鈖和宣布脱离父子关系的徐志摩父亲徐申甫的挽联。徐申甫深为儿子的死所不值,他哭道:
  考史诗所载,沉湘捉月,文人横死,各有伤心,儿本超然,岂期邂逅罡风亦遭惨劫;
  自襁褓以来,求学从师,夫妇保持,最怜独子,母今逝矣,忍使凄凉老父重赋招魂。

  张嘉鈖本因为陆小曼的缘故,徐志摩已与她离婚。可她深爱着徐志摩,徐志摩的父亲徐申甫也觉得张嘉玲是难得的好儿媳妇,所以张嘉玲一直仍住在徐家。她是这样哭徐志摩的:

       万里快飞鹏,独撼翳云遂失路;
       一朝惊鹤化,我怜弱惜去招魂。

  灵堂上,徐申甫不愿见陆小曼,张嘉鈖却不避嫌忌,走去安慰陆小曼。陆小曼良心发现,愧悔交加,两人遥遥相对,哭倒灵堂。灵堂中,徐志摩脚下的长明灯忽暗忽明,闪烁不定。
  徐志摩与陆小曼结婚五年,付出了宝贵的生命。老师梁启超的顾虑成了无法挽留的事实。徐志摩死时三十六岁,正当有为之年。陆小曼此时刚刚三十岁,正是女人最绚烂的年华。然而顶着徐志摩未亡人的头衔,自然不得不在社交场所有所收敛,社会上对她也颇不谅解。一般人尽量避免与她发生牵扯,她今天向贺天健学画、明天向汪星伯学诗,打发凄清的岁月。她干脆与翁端午同居,最后为生活所迫,连徐志摩《爱眉小扎》和《志摩日记》的版权也卖给了晨光出版公司。
  "美人自古如名将,不许人间见白头。"
  陆小曼终日疏懒困倦,打不起精神,很快地便憔悴了。她是在一九六五年文化大革命即将来临的时候,死在上海。

我的vim技巧集

平常用到的vim技巧,整理记录在blog上,方便查找。

VIM中,移动光标到下一个单词的词首,使用命令"w",移动光标到上一个单词的词首,使用命令"b";移动光标到下一个单词的结尾,用命令"e",移动光标到上一个单词的结尾,使用命令"ge"。

上面这些命令都使用'iskeyword'选项中的字符来确定单词的分界,还有几个命令,只把空白字符当做"单词"的分界。当然,这里说的"单词"已经不是传统意义上的单词了,而是由非空白字符构成一串字串。命令"W"移动光标到下个字串的开始,命令"B"移动到上个字串的开始;命令"E"移动到下个字串的结尾,命令"gE"移动到上个字串的结尾。

使用H/M/L这三个键,可以让光标跳到当前窗口的顶部、中间、和底部,停留在第一个非空字符上。H命令和L命令前也可以加一个数字,但数字的含义不再是倍数,而是指距窗口顶部、底部的行数。例如,"3H"表示光标移动到距窗口顶部第3行的位置;"5L"表示光标移动到距窗口底部5行的位置

在阅读代码时,有时我们需要根据光标所在的位置滚屏,把光标所在行移动窗口的顶端、中间或底部,这时就可以用到"zt"、"zz"和"zb"。这种滚屏方式相对于翻页来讲,它的好处在于,你能够始终以当前光标位置做为参照,不会出现翻几次页后,发现自己迷失了方向。
^_^
********************************************************************************

1.
选取多个文件用vim打开,只用一个窗口,文件都列在buffer中(这个在windows找到办法了,我用的TC+F4menu,在F4menu设置中的调用vim的"打开方式"项选择"所有文件以列表方式打开",就会将选取的文件都读进buffer,但窗口只显示一个),
gvim --remote-tab-silent
如果在命令行中,直接加参数-p即可在多tab页中分别打开文件,如:vim -p
file1.c file2.c

2. vim用什么方法显示16进制?
:%!xxd

3. 怎样在vim中粘贴进桌面剪贴板里的内容?
比如我在opera里复制的内容粘贴到vim里.
"*p
"+p

4. 在文本wrap的时候怎样才能跳到上一行而不是上一段? 如同notepad里那样?
加个g,如:gj,gk.....
d:\soft

5. 请问vim在命令行上可以复制粘贴么?
Ctrl+r"或者Ctrl+r Ctrl+w可以粘贴到命令行 "
而对把编辑区到命令行,可以先拷贝到如a寄存器,然后在命令行ctrl-r a

6. 如何实现行之间的倒序排序
比如
a
c
b
变成
b
c
a
答案::g/./m0
解释:
:h :m
m->move <address>
m0->把匹配行移动到第一行之前

这是VIM帮助文档里一个tip
:h 12.4

7.怎么实现文本的自然排序。
比如
d
a
c
b
排成
a
b
c
d
答案::sort

8. 如何删除含有某些内容的行?
例如,想要删除含有console的行,怎么写呢?
:g/console/d

9.搜索到一行如何删除该行上面的5行?
:g/string/norm d5k
:g/搜索内容/normal d5k

10. 请问怎样每隔x行插入一个空行
答:
假设每隔5行吧,
qa4jo<Esc>jq
然后 @a就可以了
或者:
:%s/\(.*\n\)\{3}/\0\r/g
3换成你要的数字

11. 如何用vim的列操作加注释
用c-v选中了一列,输入大写I或者大写A,然后输入comment符号,然后esc

12.操作多个文件其实超级简单
o newfilename
:bn buffer Next
:bp Buffer Pervious
:bN The list number N of the buffers
:sp newfile // open a newfile with a splited window
:vs newfile // open a newfile with a vertical splited window
[ctrl] +j // down window (same with the key j)
[ctrl] +k // up window (same with the key k)
[ctrl] +h // left window (same with the key h)
[ctrl] +l // right window (same with the key l)

13.一组能让你爽出内伤的 Vim motion
用vim这么长时间,当看到下边几句,对vim的认识提高一个台阶。
ci[ 删除一对 [] 中的所有字符并进入插入模式
ci( 删除一对 () 中的所有字符并进入插入模式
ci< 删除一对 <> 中的所有字符并进入插入模式
ci{ 删除一对 {} 中的所有字符并进入插入模式
cit 删除一对 HTML/XML 的标签内部的所有字符并进入插入模式
ci" ci' ci` 删除一对引号字符 (" 或 ' 或 `) 中所有字符并进入插入模式

14. 统计关键字的个数
:%s/pattern/&/g
&代表的意思就是用来表示前面比对的字串,所以做这个指令其实对档案本身并不会有什么改变。但是由於做的是全域的取代置换,vim会告诉你有从多少行中多少个字串被取代。轻轻松松很漂亮地用一行命令解决这个问题。
输入只有一行的命令:结果就会出现在最后一行上,而且不会改变到档案本身.

15. 查找关键字
可按『*』来选取关键字。不过 vim 在这里搜寻边界是根据空白或者像「 { 」、「 (
」这些符号等来决定,所以对於中文来说,这个功能可能就不是那么好用。可以用『v』选取然后『y』复制。搜索时,在『/』后,按<
Ctrl-R >然后跟上数字键 0 ,就会出现刚刚复制进入register的字串。指令如下:
/<Ctrl-R>0<CR>
在 vim的register中,register 0是作删除或是 yank 动作时,预设使用的暂存器。
不过在前面可以发现,如果我们用「 * 」作搜寻的时候,字串的前后会被「 \< \>
」夹著。举例来说,如果你找的是 \<link\>,那么, min_links
就不会符合,同样,linknode也不会符合。这也就是说「 \<
」表示的是一个字的头,而 「 \>
」代表的是一个字的尾,当你写\<link的时候,表示你要找的字,是以link开头的,同理,link\>就是以link结尾的字,所以用两个夹起来,就代表要字串的的确确是所要的那个字。

而既然有了 「*」往下找的,就有往回找的,按键是「 # 」
,你懒得记那么多的话,就用 「*」 然后搭配 「 N 」 吧!

到这里,你可能会想,如果我不想打那么多字,可是我想要的又不要完全是一样的,怎么办?
vim 也有这样的东西,就是在你打「*」之前,先加一个 「g」,也就是
g*
这样 vim 在做搜寻的时候,就不会包含 \< \> 这两个东西在前后了。同样「 #
」的使用也可以变成「 g# 」

16. 查看符号定义
Vi提供了像Win32下IDE那样的功能,可以很方便的查看函数原型、结构声明、宏的定义等。只是它的功能相比之下,要弱一些,不过,结合其它一些技巧,完全可以满足你的需要。使用这个功能,需要做一些设置:
1.
安装ctags软件包。在安装光盘可以找到,也可以到网上下载源码包,自己编译。
2. 生成tags文件。进入到你的源代码所在的目录,运行ctags
-R命令,它会为当前目录及子目录下的源程序建立索引,并在当前目录下创建一个tags文件,里面保存的是符号索引信息。
3.
设置tags路径。在vi的起动脚本文件中(一般是~/.vimrc),告诉vi在哪里可以找到tags文件,一般尽量用相对路径。如:set
tags=./tags,../tags,../../tags,../../../tags
4. 跳到指定的符号。<ctrl> + ]
可以跳转到光标所在处的符号的符号的定义那里。
5. 返回到原来的位置。<ctrl> + t 或者<ctrl> + o可以返回原来的位置。

17. 查看系统函数的帮助
Vi也可以像VC那样,很方便的跳转到系统函数的帮助那里。原理很简单,在vi运行外部命令man就行了:!man
fopen,这样做,可能会觉得有些麻烦,vi提供了快捷的方式: <shift> +
k可以跳到光标所在处的符号的帮助那里。

18. 自动定位编译错误处
在VC里,编译时,如果出现编译错误,双击错误信息,编辑器自动切换到出现错误的地方,是不是很方便呢?其实不用羡慕,vi也有这种功能,在vi里,运行make命令后,如果有编译错误,你按一下回车,vi自动定位到第一个编译错误那里。记得,要用内置的make命令,即运行:make,不是外部命令:!make。

19.自动定位查找结果
在写程序时,我们常常想知道,有哪些地方使用了某个函数,怎么办呢,你可以在shell里,用grep查找,然后打开对应的文件,可以看到相关的上下文信息。但这样做比较麻烦,Vi有个内置的grep命令,用起来很方便:
1. 查找。用法和shell中的grep一致。
2. 跳到第一个查找结果处。直接回车就行了。
3.
列出所有的查找结果。:cl命令可以列出所有的查找结果,每个结果都有一个编号。
4. 跳到某项查找结果的文件中。:cc <编号>
命令可以跳到指定编号查找结果的文件中,<编号>是前面用:cc列出来的编号。
5. 返回到原来的位置。<ctrl> + o 可以返回原来的位置。