Skip navigation.

生活周遭

In My Circle

???GFW???? <a href="http://blog.leirahua.com" target="_blank"><a href="http://blog.leirahua.com" target="_blank">http://blog.leirahua.com</a></a>

不幸的,这儿终于也被GFW了~ 一次次的逃离搬迁,终于还是没有摆脱GFW的魔爪。

不得已,终于选择了在国内的BSP。这次是朋友推荐的yo2,似乎不错,还可以帮自己的域名,闲置已久的 LeiraHua.com 也终于排上了用场。

现在的地址是 http://blog.LeiraHua.com 希望大家看到这贴,能够去新的地方。

Tips: find到带空格文件名用xargs处理的技巧

, ,

find和xargs是最好的组合,可以说是linux shell下的瑞士军刀,用xargs配合find,比直接用find的-exec参数,速度更快,用法也更直观。
基本的用法比如:
find ./ -name '*.bak' | xargs rm -rf

一般情况,上面这个命令运行的很好,但是如果找到的文件名代空格,上面的命令运行就可能会出问题了。

find有一个参数-print0,于默认的-print相比,输出的序列不是以空格分隔,而是以null字符分隔。而xargs也有一个参数-0,可以接受以null而非空格间隔的输入流。所以说xargs简直就是为find而生的。上面的问题就很好解决了:
find ./ -name '*.bak' -print0 | xargs -0 rm -rf


Unicode 与 UTF-8, GBK

,

原本是为了回复[python-chinese]邮件列表中的一个关于socket上传输unicode的问题,写得比较长,觉得应该记下来:

我想这里有几个概念要澄清~ 这样才能有比较好的交流的基础,而不是说同一个名字,却各自指的不是同一个东西。我也只是班门弄斧,希望大家指正。

unicode是一个字符集,不是一种编码,她只是定义了一个字符空间,把字符集中的字符映射到了相应的整数上,并为每一个字符提供了唯一的名字,比如,'中' U+4E2D。但unicode并没有定义编码方式(codec),也就是从字符集到字节序列的映射方式。有专门为unicode定义的编码方式,比如utf-8,utf-16(be/le),他们定义了unicode字符到字节序列的映射,也就是编码。utf-16简单的用16bit两个字节来编码(encode)unicode,utf-8用1倒3个或者更多的字节编码(encode)一个unicode字符。这些codec同时也定义了如何从一个字节序列中decode出unicode字符序列的方式。所以,unicode是一个抽象的字符概念,并不是一个字节流,她到字节流的映射靠codec来完成。python中,用unicode对象来表示抽象的unicode字符,我觉得到这个程度就可以了,不必关心其中是不是靠整数来表示的。关键是string对象就是字节流,python的unicode对象不同于string对象,抽象的unicode对象到字节流的string对象之间需要靠codec来转换。(在py3k中可能要统一unicode和string对象,再
议)
而gbk也是一个字符集,但同时他也定义了gbk这种codec(一种mbcs的codec),它定义了一个gbk字符(英文或者中文)到字节序列(一个或者两个字节)的映射。因为unicode的集合比gbk大,使gbk的超集,所以,可以把gbk编码的字节流转换成unicode字符序列,也可以把一部分的unicode字符(gbk子集的部分)编码为gbk的字节序列。所以,gbk也可以作为unicode的一种codec来用。

比如:(我现在在windows下面,所以默认的编码就是gbk的)
>>> sgbkzhong = '中'#输入默认gbk编码的string对象
>>> sgbkzhong#这是个以gbk编码的两个字节的字节流
'\xd6\xd0'
>>> len(sgbkzhong)#所以她的长度是2
2
>>> uzhong=unicode(sgbkzhong,'gbk')#可以将这个字符序列decode成unicode对象
>>> uzhong#这个unicode是U+4E2D
u'\u4e2d'
>>> len(uzhong)#这个unicode字符序列的长度是1
1
>>> sutf8zhong=uzhong.encode('utf-8')
>>> sutf8zhong
'\xe4\xb8\xad'
>>> len(sutf8zhong)#编码成utf-8的字节流,长度是3
3
>>> sutf16bezhong=uzhong.encode('utf-16be')
>>> sutf16bezhong
'N-'
>>> len(sutf16bezhong)#编码成utf-16be的字节流,长度是2
2
>>> sutf16bezhong.encode('hex')#我们看一下'N-'对应的hex
'4e2d'
>>>

以上说明的是python中unicode和string(字节流)之间的关系。而socket接口只能传输字节流,她并不关心你的内容是什么,自然也不能传什么抽象的unicode对象,她只能传输将unicode编码过的字节流。所以,python的socket接口只能处理string对象,如果不是string对象,会被首先转换成string对象。


具体到你这个问题,

On Thu, 23 Nov 2006 13:34:45 +0800, limodou
<limodou@gmail.com> wrote:

> On 11/23/06, 隋刚 <blackjacksg@gmail.com> wrote:
>> 实在是头大了,我又尝试了一下,因为是跟vc写的客户端(使用了unicode编码)进
>> 行通讯,分析了一下里面的数据,发现在每一个客户端发过来的字符前面加入了
>> '00',而不管我怎么转换,发过去的都是8位的ASCII字符,看看有什么好的解决办
>> 法没有?
> 那它可能使用的是utf-16-be编码吧。如:
> >>> a.encode('utf-16-be')
> '\x00a'

我想limodou已经替你解决了,我的理解和他一样,你的vc的客户端使用的应该是utf-16be的编码,不知道你使用这种方法后的结果怎么样了。

至于你之前的代码,为什么直接send unicode对象,对方却接收到的是ascii字符串,原因是send()函数会把你的unicode对象用str()转换成string对象,使用的codec是你指定的'utf-8',因为都是英文字符,所以,utf-8编码的结果是和ascii一致的。

On Mon, 20 Nov 2006 17:58:49 +0800, 隋刚
<blackjacksg@gmail.com> wrote:

> 请问使用python的socket module发送unicode的信息怎么发送,我试着转换了一
> 下,发送到服务器端还是ascii的,可以看看我的源程序,谢谢。
> import socket
> import sys
> reload(sys)
> sys.setdefaultencoding('utf-8')
> host = "192.168.3.111"
> port = 8888
> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> s.connect((host, port));
> str = u'<?xml version=\"1.0\" ?><Request type=\"Distribute\"/>'
> s.send(str)
> date = s.recvfrom(4096)
> s.close()
> print repr(date)


顺便推荐一下这篇FAQ,对Unicode讲解得很通透,让我明白了很多原先很混乱的概念。
UTF-8 and Unicode FAQ for Unix/Linux
这儿有一个捎老一点的中文版

用p4命令行作打包修改中的changelist

发现这种heavy GUI的工具,非常不灵活,非常难用,能做什么都是定好的,想要做点没有预订好的事情根本就是不可能的。Perforce就是,非常怀念cvs/svn。
想要把一个正在修改的changelist给同事,发现p4的GUI根本不能做patch,命令行好像也不行。想想,做出个diff格式的patch,同事也未必能用(windows世界...)。于是,饶了个大弯路,写了个长命令,用于打包本地changelist的文件:
p4 change -o  14563 | grep --color="never" -o "//depot/[^ ]*"  | cut -c 40- | xargs tar rvf patch.tar

最后之所以用tar rvf而不是jcvf,是怕xargs接到的文件列表太长,分几次传给tar。最后的tar,你要bzip2还是gzip就随意了。

安装本地的firefox theme

一般firefox的extension都是打包成xpi文件的,本地的xpi文件直接用firefox打开就行了。可是firefox的theme却是打包成标准的jar文件的,直接打开本地的jar就不行了。简单的放在一个html文件的a标签内也不行,就变成下载了。
theme的安装需要一段javascript代码,这段代码可以直接从mozilla的add-on下载站引用就行了。以本地的TangoFF_2_0.jar为例,可以这么做,写一个简单的html文件,也不必求完整:
<head>
<script src="http://addons.mozine.org/js/install.js" type="text/javascript"></script>
</head>

<a href="./TangoFF_2_0.jar" 
   onclick="return installTheme(event,'TangoFF 2.0', 'images/default.png');" >
 Install Theme Tango for Firefox 2.0
</a>

然后用Firefox打开,点机连接就可以了~

夜宴?晚饭。

自从张艺谋的英雄开了中国“武侠大片”的先河以后,还真是一部不如一部。这次夜宴又一次让我们感受到了“大片”对于“烂”的创造力是超出我们的想象的。比无极的馒头更厉害的是,这次夜宴还没上映,就有人早早的作了一部恶搞video热身了。而我到现在才知道这个"晚饭",也算是后知后觉了。赶紧传到YouTube上恶补一下。PS:这还是我第一次往YouTube上传video呢:


udev的static device node

,

这两天帮QA的同事安装nistnet,使用中发现,每次reboot以后,都会丢失/dev下所需的设备节点,包括/dev/nistnet,/dev/hitbox等。后来我想到ubuntu使用udev来动态建立设备节点,应该是reboot的时候,udev没能正确的重新建立这些节点。于是,需要udev建立这些静态的设备节点。

google了一下,在LFS中找到了方法。udev的init script会把/lib/udev/devices/下预建立的静态device nodes拷贝到/dev下面。所以,只要把需要的static device node预先mknod到/lib/udev/devices下面就行了。

李波:民主的四大渊源

转自胡码乱缠对谈录

转载四 李波:民主的四大渊源

当代最卓越的民主理论家之一的罗伯特□ 达尔认为,现代民主的理论和实践有四大渊源:希腊的直接民主制、罗马与中世纪、文艺复兴时期意大利城市国家的共和主义、代议制政府的理论与实践,以及政治平等理念。本文拟对达尔指出的民主的四大渊源作一简单介绍和评论。

Read more...

美国的民主是什么——一个收银机的故事

转自胡码乱缠对谈录

转载三 美国的民主是什么——一个收银机的故事
    
       作者:丁林
    
如果说那么多从深思熟虑的哲学系统里产生出来的“社会理想”,在实行过程中都会产生很严重的问题。那么为什么在“革命”之后,看上去还处于比较自然状态的、没有一大群哲学家的美国,在必要的时候,反而能够搞出一部200多年不变的宪法,并且,平稳地选了40几次总统、搞了几十次和平的政权交接呢?
    
在回答这个问题之前,我想先简单地讲一个典型的美国式的发明小故事。

Read more...

分饼的政治学

转自胡码乱缠对谈录

转载二 分饼的政治学

一个简单的日常生活问题包含着极其深刻的政治学:

两个贪心饿鬼要分一个饼吃。而这俩都不是省油的灯,谁要怀疑他少分了一丁点都跟你没完。你说他们应该怎样切才公平?

很多人会想,这还不简单。从正中二一添做五,平均主义。因为这世界不患寡而患不均。行不行?可你忘了,这两人拿到自己那一半时,眼睛还会盯着另一半。心想他那半拉子里夹的是花旗参,我这半里一定是萝卜干。我非干他不可!

我们中国人号称文明悠久,聪明过人。可我们到今天还没有想清楚这么个简单问题。五千年过去了,我们的思路还停留在盼包公转世,或哀求当政者“民为本,社稷次之,君为轻。”眼巴巴地期望分饼人刀下留情,让我等还有活路。

还有一批文人甚至摇唇鼓舌,说只要经济发展而把饼做大点,怎么腐败分法都行。听得我都要吐。

马克思的分法是先“各尽所能,按劳分配”,后“各尽所能,各取所需”。可惜他治学缺乏严谨,搞不清楚到底怎么按劳分配,谁来分配。其门徒也不闹明白,胡来一气。留下一个永远理不清的烂摊子。

老马及后来的小马们,似乎也觉得不对。因此又有更荒谬的解决办法:把这两个小气鬼改造成共产主义新人。于是怎么分都无所谓啦。也不想想做不做得到。

这个简单而深刻的问题有着简单得不能再简单的答案:分权制衡!

Read more...

什么是民主?(转)

按说,web的精神就是超链接,信息的复制除了造成冗余,并没有意义。不过,这是在每一个链接源都能够长期存在的理想前提下。这是个GFW的时代,什么信息都可能消失在大墙之外。所以,我也做起了抄书匠。这篇文章我也是n道贩子了,也就不追本朔源了,我转自胡码乱缠对谈录

转载一 什么是民主?

民主是什么呢?很多人一定会说,这个问题很简单嘛,民主就是代表大多数人的意愿,比如有5个人去旅游,4个人想游泳,1个人想打球,那么民主的决策一定是去游泳,如果最后的决策是去打球,那就变成专制了。

可别忙,当我们把上面的例子稍微改变一下,你就会惊愕地发现,这个"民主"竟然是只披着羊皮的大尾巴狼:比如5个人中有4人认为1人该死,那么民主的决策就是"合法"地把那个可怜的家伙杀死!

你也许会说,这没什么错啊,如果大家都认为一个人该死,那他怎么可能没罪呢?不幸的是,的确有这种可能。事实上,民主的内涵远非"大多数"这么简单,为了弄清楚这个问题,我们只好把那些陈旧的历史书从垃圾桶里翻出来,仔细读一读。

Read more...

骗一个zooomr的pro账号

,

dororo exdororo exHosted on Zooomr
上面的图片纯粹是为了骗一个zoomrpro账号。不过我承认,我还是更喜欢这个穿花衬衫抠PP的Dororo,hoho。

Tips: grep, output only matched patterns

, ,

"sed的in-place edit选项,和RTFM"中,说到过:

...关于 Search and Replace 和 Regular Expression,还有一个问题困扰我,在这儿记下来。 就是将文件中符合某个pattern的字符串打印出来。注意,只是符合这个pattern的字符串本身,而不是所在行。直接一看,这怎么都是grep的工作嘛,可以在对grep狠狠的RTFM以后,还是未果...


GNU grep's new features上看到

If you haven't been paying attention to GNU grep recently, you should be happily surprised by some of the new features and options that have come about with the 2.5 series. They bring it functionality you can't get anywhere else -- including the ability to output only matched patterns (not lines), color output, and new file and directory options.


于是特地又看了一下grep的man page,我手边的是公司里cygwin下的grep-2.5.1a,果然有这么一个参数:
  -o, --only-matching       show only the part of a line matching PATTERN

试了一下,真是好用。看来是2.5系列新加的功能。(不过现在又不免想,是不是早在发sed的in-place edit选项,和RTFM,grep就已经有-o可用了?汗~……)

斯德哥尔摩综合症

下面的文字转(抄:-)自巴蛮子的新破茅屋,原封不动的抄在下面:


上期的《三联》有一篇文章在讲“斯德哥尔摩综合症”,记得这个名词俺当初还是在X档案中文网中看到的,后来在香港的《谈判专家》中也听见过。看来看看电视有时也可以学到一点东西。

斯德哥尔摩综合症是一种精神上的依赖,是劫持者和被劫持者之间产生的相互依赖关系。劫持者会逐步 “威胁你的生命,恐吓你,但是不会杀了你” (Symonds, 1980)。来自死亡的威胁会加剧被劫人质的感恩感和恐惧感。使被劫持的人质不愿意违背劫持者或是恐怖分子的意愿。



“受害人”想要活下去的意愿远远大于憎恨这些使他们陷入进退维谷处境的人。”(Strentz, 1980)受害人开始认为劫持他们的人是“好人”,甚至是救世主。这种情况...的发生于以下四种特殊情况:

1. 一个人威胁要杀害另一个人,而且看上去有能力做到。

2. 另一个人不能逃跑,他或是她的命运就掌握在提出威胁的人 手里。

3. 被威胁的人孤立无援,她唯一可以接触到的人就是这个威胁他 的人。

4. 威胁者会对被威胁的人不定的表现出仁慈。


//
受害人为了生还采取的观察策略

受 害人必须把所有的全副精力集中在生还上,这需要避免直接受到毁灭性的杀害。他们开始用尽一切方法协调劫持者的反应,包括好的反应和不好的反应。结果是,受 害人对于劫持者非常了解,而忽略了自己。受害人的心理特征会逐步变成:依赖性,被动,没有行动,决定,思考的能力等等。他们会设法讨好劫持者。所有反应的 形成都是为了活下去,其中包括否认自己处境,注意劫持者的喜好,对于劫持者的存在充满恐惧,他们害怕现在的情况会被警方打破,以及对劫持者看法的认同。人 质们会对恐怖分子充满感激之情,他们认为是恐怖分子给了他们生还的机会。他们把注意力全都集中在劫持者的仁慈上,忘了他的暴行。被殴打的女性甚至会认为施 暴者是个好人,她可以帮助他解决他暴行的根源问题。受害人不仅对劫持者感到害怕,同时还会爱上,或是同情对他们展现过仁慈的劫持者。 劫持者的任何一点仁慈的行为都会帮助被劫人质缓解巨大的精神压力。

事实上,被劫人质在被解救之后会去监狱探视劫持他们的人,他们会要求为被告人辩护,甚至提供辩护所需费用。这生动的表现了被解救出来的人质和生还者为了尽量减少已经造成的伤痛而拒绝合作告发劫持者。
对恐惧和愤怒的否认,以及认为劫持者是无所不能的使受害人在心理上依从着劫持者。高度焦虑使受害人无法看到其他的可能性。从而心理压力逐渐升级。

Tips:autossh

, , ,

SSH的特性就是安全,如果一个连接长期闲置,那么就可能被利用,所以SSH服务端一般都会有一个超过Idle时间踢出的设置。不过像我们经常会用SSH登陆到远程服务器上长时间的工作的,这个特性就非常不方便了。于是autossh,就是这么一个牺牲安全性,换取便利性的工具。

autossh通过建立另一个SSH连接来监视工作SSH连接,当工作连接断开的时候,能够自动发起重连。不过你得设置ssh-agent,否则,重连的时候还是会提示你输入密码的,这样就失去意义了。

不过,就算是重连,你正在做的工作也会因为失去连接登出而都被杀死的。这时候就该GNU screen登场了。在你ssh到远程服务器的时候,启动一个screen Session,screen可以让你在ssh失去连接的时候自动detach,然后重连上来的时候,只要用screen -D -R取回screen Session就可以了。而且,autossh自带了一个非常好用的script rscreen,已经完完整整的帮忙做好了这件事情,只要直接拿过来用就可以了。

至于安装嘛,对于Debian,照例只要apt就可以了,下面贴一下我的对rscreen的小小修改,去掉了不需要的键设置,使用remoteSSH做为screen Session的名字以区别其他的screen Session,接收全部的ssh参数:

 
--- /usr/share/doc/autossh-1.3/examples/rscreen 2005-03-23 10:05:20.001000000 +0800 
+++ /usr/local/bin/rscreen  2006-05-16 11:41:23.705698100 +0800 
@@ -23,4 +23,4 @@ 
 #AUTOSSH_PATH=/usr/local/bin/ssh
 export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME AUTOSSH_PORT

-autossh -M 20004 -t $1 "screen -e^Zz -D -R" 
+autossh -M 20004 -t $* "screen -D -R remoteSSH" 

Vim7的新功能

也算用vim很久了,这次vim7发布,倒也是第一时间升级的,不论是家里的Debian还是公司的Windows,但是对Vim7的更新真的没有太在意。这次看到LGJ的贴文Vim7 的新功能点名了Vim7的几大主要更新。

我觉得其中最吸引我的可以说是getscript plugin的特性了。本来维护Vim这么多的plugins就是一件很麻烦的事情,特别是像我这样在很多机器上都会用到Vim,希望能够同步各个机器上Vim配置的,更是一件麻烦的事情。而且,Plugins多了,散落在vimfiles目录中,时间久了,连自己都搞不清楚具体装了哪些Plugins了,要清除一个Plugin就更费劲了。现在有了getscript plugin,只要对自己的常用的plugins写一个GetLatestVimScripts.dat,到时候:GLVS一下,就OK了。简单,清晰,而且还能非常清楚的跟踪自己所安装的plugins,更方便与大家共享。

决定接下来有空了整理一下自己的Plugins,写出一个GetLatestVimScripts.dat,贴上来和大家分享。

Pyrex, 和Python的C扩展

,

这原本是回复到[python-chinese]邮件列表的,但是没有回复进去,可能是因为功过Gmane news服务器的原因。先转到这儿:

倒是这两天我也在看这方面的问题~
一般编写Python C/C++ Module,或者为C/C++ lib编写Wrapper,我所看到的有以下几种方式: 1. 直接使用C Python提供的API 2. SWIG 3. Boost.Python 4. Pyrex

首先直接使用Python C API是很不方便的。上面几位高人已经谈过了SWIG和Boost.Python,我就不多说了,只是个人感觉易用性而言Boost.Python > SWIG,但SWIG功能强大,支持的也不只是Python一种脚本语言。以上这两种方式对C++的支持都比较友好。

这里着重推荐一下Pyrex。 Pyrex可以说是扩展Python的一大创新,她使用Python like的语法来编写Python的C Module,自动翻译成C语言代码,进而编译获取C代码的高效率。而且,配合Python的Distutils,使得构建过程简单到了只需要setup.py的程度。我觉得其简化python扩展的编写方式,已经和Boost.python,SWIG不在一个意义级别上了。

这里贴一段来自pyrex的示例,用于搜索质数:

# primes.pyx
#
#  Calculate prime numbers
#
 
def primes(int kmax):
        cdef int n, k, i
        cdef int p[1000]
        result = []
        if kmax > 1000:
                kmax = 1000
        k = 0
        n = 2
        while k < kmax:
                i = 0
                while i < k and n % p <> 0:
                        i = i + 1
                if i == k:
                        p[k] = n
                        k = k + 1
                        result.append(n)
                n = n + 1
        return result

将其pyrexc编译后得到一个c文件,然后编译之后就是一个python module了~ 按照他的逻辑,我还对照相应的写了一个Python脚本:

#!/usr/bin/env python
# primespy.py
 
def primes(kmax):
        result = []
        if kmax > 1000:
                kmax = 1000
        k = 0
        n = 2
        while k < kmax:
                i = 0
                while i< k and n % result != 0:
                        i += 1
                if i == k:
                        result.append(n)
                        k += 1
                n+=1
        return result
两者的代码行数基本一样,来看一下运行结果:
In [23]: tpyx = timeit.Timer(stmt='primes.primes(1000)', setup='import primes')
 
In [24]: tpy = timeit.Timer(stmt='primespy.primes(1000)', setup='import primespy')
 
In [25]: tpyx.timeit(100)
Out[25]: 1.2969999313354492
 
In [26]: tpy.timeit(100)
Out[26]: 30.266000032424927
速度提高了30倍之多!

pyrex的优势是编写简单,不必处理多余的细节,而且也不需要为这种简单付出效率的代价。劣势在于目前的pyrex对C++的只是仍然不是很好,还在继续开发之中。至于对C++到地支持差到什么程度,我还没有进一步测试过,还希望看到各位的高见。

总结是,如果是针对C的Python扩展,或者lib Wrapper,Pyrex可以说是最方便的选择。如果涉及到C++的扩展,可 能目前boost.python还是最好的选择了。

补:目前正在看Boost.python,SWIG其实并没有细看过,呵呵,只是看了一些intro性质文章,就开始大发厥词了,希望大家补充指正。

fglrx ATI Linux driver进入Debian了

,

这算是一个旧闻了。
原本安装ATI的fglrx必须自己编译安装,虽然可以借助Flavio Stanchina的fglrx-installer,更新之类的问题也还是挺麻烦的。现在进入offical Debian了,就方便多了。其实,kernel module还是需要编译的,不过,在Debian强大的module-assistant或者kernel-package下,还是很方便的。
可惜,Debian的fglrx-driver只有i386的,没有x86_64的。这也算是给我最近计划的重装系统又找了一个借口吧。

Tips: 图片格式的批量转换

, ,

手上有一堆很大的tif图片,想要批量转成尺寸小一点的jpg图片。对于图片处理,特别是批量的时候,命令行工具imagemagick可以说是最好不过的工具了。
一般对于处理转换图片,imagemagick提供了convert和mogrify两个工具,convert一般用于处理完后输出到另一个文件,而mogrify一般用于修改源文件,但是如果指明不同的格式,mogrify也会保存到另一个不同扩展名的文件中去。这里我要用到的就是magrify。
命令很简单:
ls *tif | xargs -n1 mogrify -format jpg -resize ">1024x1024"

xargs的强大,这里就不说了。这里主要涉及mogrify的两个参数,-fromat和-resize。-format指明格式,这里是jpg。-resize就是要修改尺寸,这里用的是">1024x1024",意思是输出图片不能大于1024x1024,这也是一个很方便的用法,这样,输出的图片最长的一边都不会超过1024,大小都比较统一。如果只是指明 -resize 1024 的话,只能保证横向宽度为1024,如果是纵向较长的竖图片,可能就会变成1024x1540之类的尺寸,大小就不统一了。

imagemagick非常强大,并且具备命令行工具特有的方便和适于脚本的特性,非常适合于批量处理。除了上述的例子,我原先还用imagemagick写过一个批量添加png图片透明层的简单脚本,不过不知道扔哪儿了,回头找找再帖上来。

手机界面:从基于应用到基于任务

MobiFace看到这么一个创意。讲的是我们目前的手机界面都是基于应用(Application-Based)的,我们必须先进入某个应用,然后才能使用其功能。而基于任务(Task-Based)的界面,则用户只需要专注于将要完成的任务即可。

比如用户输入25。这可以是一个电话号码的起始。也可以是25分钟的一个计时器。或者是25美元想要转成欧元单位。又或者是一组他想记下来备忘的代码。

用户输入82,并且转入英文状态的话,那么他输入的是字母TA. 也许用户是想要给他的朋友Taylor打电话。或者这是一个个短信"take me fishing this weekend"的起头。或者这是"take the trash out"的一个提醒。也或者是一个网址 tadalist.com. 事实上这些可能的选项是有限的,可以被正确判断并且显示出来。而他们的顺序可以是固定的,或者按照使用频度来排序。

Tips: procmailrc规则中的中文处理

, ,

procmail有很方便的基于正则表达式的规则,非常强大。 处理英文字段自然OK,可是处理中文字段呢?直接打中文恐怕是肯定不可以了。比如分类Subject段包含“中国”的规则,如果写成:
* ^Subject.*中国
那就找不到了。因为procmail直接处理邮件文本,而邮件文本都是编码过的,Subject段是肯定不会直接出现“中国”字样。 一般邮件内容的编码常用的有两种,QuotedPrintable和Base64,下面分开说。
QuotePrintable
用文本编辑器直接打开mbox文件,在Subject段看到
=?utf-8?Q?Goowy=e9=82=ae=e4=bb=b6=e6=9c=8d=e5=8a=a1=e7=9a
=84flash=e7=95=8c=e9=9d=a2_=5bFlickr=5d?=
这样都是=间隔的,就是QuotePrintable编码了,其中头部=?utf-8?Q?中的Q也指出了这儿用的是QuotePrintable编码,utf-8不用解释,就是文本是utf-8编码的。以上的Subject段解码后是:
Goowy邮件服务的flash界面_[Flickr]
对于QuotePrintable的Procmail规则就比较简单,直接根据关键字的编码,加入=号间隔就可以了。比如我们查找关键字“服务”,对应的utf-8序列是
0xe69c8d 0xe58aa1
,一般中文自的utf8编码都会是3个字节,那么对应的就是
=e6=9c=8d=e5=8a=a1
,规则可以这么写:
* ^Subject.*=e6=9c=8d=e5=8a=a1
对于GB系列编码也是一样,只是每个汉字就是两个字节,而不是三个了。
Base64
Base64的嘛,hoho,再研究研究~ 等下回吧~

Tips: ssh记住密码,自动登录

, ,

ssh登录,每次都要敲密码,敲多了自然是烦。而且ssh的安全性,使它不能在任何配置文件中或者命令行参数中直接指出密码,所以只能不厌其烦的每次等待登录框出现,然后敲入密码。特别是使用ssh认证的cvs,svn之类的,更是影响工作情绪。ssh-agent就是用于解决这个问题的:
1. Creating authentication key
用ssh-keygen生成公/私钥对:
  beowulf% ssh-keygen -t rsa
  Generating public/private rsa key pair.
  Enter file in which to save the key (/u/kim/.ssh/id_rsa): [RETURN]
  Enter passphrase (empty for no passphrase): litt1e 1amp jumb3d
  Enter same passphrase again: litt1e 1amp jumb3d
  Your identification has been saved in /u/kim/.ssh/id_rsa.
  Your public key has been saved in /u/kim/.ssh/id_rsa.pub.
  The key fingerprint is:
  b7:18:ad:3b:0b:50:5c:e1:da:2d:6f:5b:65:82:94:c5 kim@beowulf.gw.com
记住你的passphrase(这里是little lamp jump3d)。其中~/.ssh/id_rsa.pub为公钥文件
2. Authorizing access
将公钥上传成目标机的~/.ssh/authorized_keys (ftp,scp都可以)
  beowulf% cd ~/.ssh
  beowulf% cp id_rsa.pub authorized_keys
  beowulf% scp -p ~/.ssh/authorized_keys kim@hrothgar:.ssh/
  kim@hrothgar’s password: YourPasswordHere
  authorized_keys               100% 1839     1.2MB/s   00:00 
其中需要输入目标机上你的用户密码(在此为hrothgar上的kim用户)。 这时,你使用ssh登录时,将会通过你identification的passphrase来登录了。
  beowulf% ssh hrothgar
  Enter passphrase for key '/u/kim/.ssh/id_rsa': litt1e 1amp jumb3d
  kim@hrothgar% 
3. Keeping authentication keys in memory
通过ssh-agent来记住认证,添加的方式见下一节。一般的做法是通过ssh-agent来启动一个shell,在该shell中使用:
  beowulf% ssh-agent $SHELL
  beowulf% 
我用的是Debian,在/etc/X11/Xsession.d/下面就又一个90xfree86-common_ssh-agent用于使用ssh-agent来启动X,这样,一进入X,ssh-agent就是可用的。如果你的系统里没有这样的设置,简单的做法就是用"ssh-agent startx"来启动X,如果你用的是xdm,gdm之类的,修改你的~/.xsession文件
4. Managing keys in memory
通过ssh-add添加keys。
  beowulf% ssh-add
  Enter passphrase for /u/kim/.ssh/id_rsa: litt1e 1amp jumb3d
  Identity added: /u/kim/.ssh/id_rsa (/u/kim/.ssh/id_rsa) 
然后,你就可以通过
  beowulf% ssh hrothgar
  kim@hrothgar% 
ssh登录而不需要密码了。

Firefox Space Bar无法滚屏的问题

突然一天发现Firefox出现了Space Bar无法滚屏的问题,并且并发有Home/End无法滚屏到顶部和底部的症状。还有特征是有一个文本编辑的光标竖线出现在文本当中,可以用键盘的方向键滚动。召唤了Google大神,在Firefox customizations (Notes)上找到了答案。原来是开启了“Allow text to be selected with the keyboar”选项的问题,这个选项在Preferences->Advanced->Generel下。也不知道什么时候打开的这个设置,不过至少,解决了~

sed的in-place edit选项,和RTFM

, , ,

Debian Administration上看到Search and replace across many files with a perl one-liner这篇文章。多文件的Search and Replace的Linux风格处理方式,也是我一直思考的,这篇文章提供的是一个perl的解决方案。而对于这种问题,最直接想到的解决方案应该是sed吧?而且对于Perl,我到现在还是个门外汉。

不过一直以为sed不能直接对源文件修改,必须重定向到新文件,所以觉得在批量处理中很麻烦,因为每次都必须指定新文件名,然后在覆盖回源文件。为此还傻傻的专门写过一个runsed的shell脚本用于处理重定向到中间文件再覆盖回源文件的工作,让sed可以直接修改源文件,适用于批量处理。还沾沾自喜,以为找到了最终的解决方案。

在上面这篇文章中,比较关键的是用到了perl的 -i 参数edit the files in-place,直接修改源文件。这时候我想,sed也是应该有这么一个in-place edit的选项的,只是我以前没有找到罢了。于是man sed,然后在man page的32行就看到了

-i[SUFFIX], --in-place[=SUFFIX]
                edit files in place (makes backup if extension supplied)
这个参数。这时候才觉得自己好傻,没有好好的RTFM,而且还好好的自作聪明了一把。 sed的这个 -i[SUFFIX], &ndash;in-place[=SUFFIX] 参数功能还真的很强,除了能够直接修改源文件,还能自动备份源文件,指出备份文件的suffix,真是非常方便。(居家旅游,杀人灭口,必备良药?XD)又可以快乐的sed生活了。

现在,关于 Search and Replace 和 Regular Expression,还有一个问题困扰我,在这儿记下来。 就是将文件中符合某个pattern的字符串打印出来。注意,只是符合这个pattern的字符串本身,而不是所在行。直接一看,这怎么都是grep的工作嘛,可以在对grep狠狠的RTFM以后,还是未果。真是奇怪,总觉得打印搜索到的pattern本身,比打印行要容易的多嘛,怎么会这么难找?Python脚本自然可以很容易就实现,但是总觉得已有的shell工具肯定是有这样的功能了,只是我没找到罢了。希望有达人指点。(不要告诉我grep后sed哦~)

测试 Blog

测试
December 2009
S M T W T F S
November 2009January 2010
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31