
2012年4月13日
https://www.jianshu.com/p/ebf2e5b34aad
posted @
2018-11-18 16:56 Seraphi 閱讀(157) |
評論 (0) |
編輯 收藏
今天換了Macbook pro來寫畢業論文,發現有一大堆中文相關的問題導致編譯錯誤。經過一晚上的研究,終于解決。主要有以下要點:
1. 由于MacTex對CTex的支持并不如TexLive那么好,在用pkuthss 1.7.3模板寫論文的時候,首先需要對pkuthss.cls文件進行修改:
需要將原來的\LoadClass[hyperref, cs4size, fntef, fancyhdr]{ctexbook}[2011/03/11]一行改為如下形式:
\LoadClass[fontset = windowsold,cs4size,UTF8,fancyhdr,hyperref,fntef,openany]{ctexbook}[2011/03/11]
2.在進行上述改動后,發現還是不行。提示simhei.ttf, simsong.ttc, simfang.ttf找不到。這個時候,需要將上述三種字體超鏈接到tex的目錄下。
具體方法如下:
(1)在tex對應的下列目錄建立Chinese文件夾:/usr/local/texlive/2016/texmf-dist/fonts/truetype/
(2)將SimHei SimSong Fangsong三種字體超鏈接到上述目錄。這三種字體可以在/Library/Fonts/Microsoft中找到,注意的是放到tex下時,文件名需要小寫,黑體和仿宋后綴名為.ttf,宋體為.ttc
(3)sudo texhash
3.再編譯的時候發現已經可以了!Yeah~~~
posted @
2017-02-28 22:13 Seraphi 閱讀(528) |
評論 (0) |
編輯 收藏
I have successfully run your code after doing the following two steps:
Download GLPK from
http://sourceforge.net/projects/winglpk/files/latest/download (as mentioned by oyvind)
- Unzip it into (for example) :
C:\glpk_is_here\
Add GLPK binaries to your system path before running python C:\>set PATH=%PATH%;C:\glpk_is_here\glpk-4.55\w64
Using the same cmd window from (3), use python/ipython to run your code:
C:\>ipython your_code.py
See the results Out[4]: 2.0
Good luck.
posted @
2016-05-27 14:25 Seraphi 閱讀(669) |
評論 (0) |
編輯 收藏
原貼:http://www.cnblogs.com/ajunForNet/archive/2012/09/12/2682063.html
組長說在內網部署一個論壇,這可難不倒我,裝個Discuz嘛。
部署環境就一臺普通的PC,四核i3,Windows7。這就開搞了。
準備工作
系統是Windows 7 專業版,自帶IIS7.5(家庭版不帶)。IIS7開始帶了FastCgi,對PHP支持好了許多,所以也不必裝Apache啦。
下載 PHP 5.4、 MySQL 5.5 以及Discuz X2。
對于IIS7 FastCgi,我們應當選擇VC9編譯的線程安全的版本。
安裝PHP
解壓PHP,我給的路徑是C:\PHP,大伙兒隨意
把php.ini-production改名為php.ini(用于開發環境的話,就改那個development)
修改擴展路徑
extension_dir = "./ext"
啟用MySQL擴展(即去掉分號)
extension=php_MySQL.dll
修改時區
date.timezone=Asia/Shanghai
完了可以嘗試在命令行中執行以下PHP:
cd C:\PHP
php -v
可以看到php的版本信息,如果把dll文件不存在的擴展打開了的話,會有提示。
配置IIS
IIS容易對付,不過先得把確保這幾項已經裝上:

1、添加模塊映射
啟動IIS管理器,對服務器設置“處理程序映射”,”添加模塊映射“:
(圖)
注意,設置可執行文件路徑的時候,要選擇exe。

2、添加index.php為默認文檔
對服務器設置“默認文檔”,添加index.php
3、創建新站點
接著在創建一個新的站點,并創建一個目錄存放你的網站,C:\Forum
主機名填你想要綁定的域名,對于一臺服務器上有多個網站的情況,域名幾乎是必須的。
當然啦,內網的話,就改hosts隨便弄個上去吧。
4、設置程序池
去應用程序池,設置剛才創建的站點對應的程序池,把.Net framework版本設成無托管代碼。
重啟IIS,在網站目錄下放一個index.php,內容很簡單:
<?php phpinfo(); ?>
訪問網站,設置無誤的話應該能看到PHP的系統信息。
安裝MySQL
安裝MySQL挺容易的,按照Discuz給出的教程就可以了。
因為我下的是UTF8版本的Discuz,所以在選擇字符編碼那一步選的UTF8。
至于改數據庫目錄以及移動那個dll,看上去完全沒那個必要,我也就沒弄。
安裝Discuz
最煩的都搞定了,最后把安裝包里upload里面的東西都復制到網站目錄下,
訪問網站下的install目錄就能看到安裝界面
剩下的不用說了吧···
得記得安裝完了以后,進UCenter->全局->域名設置->應用域名,把論壇的域名給設好了,
否則論壇首頁就是個500
Over.
posted @
2013-03-11 11:09 Seraphi 閱讀(585) |
評論 (0) |
編輯 收藏
nohup + 命令 + & 后臺運行程序(連接服務器時,運行程序)
posted @
2013-03-06 10:38 Seraphi 閱讀(254) |
評論 (0) |
編輯 收藏
摘要: LaTeX( LATEX,音譯“拉泰赫”)是一種基于TeX的排版系統,由 美國 計算機學家 萊斯利·蘭伯特(Leslie Lamport)在20世紀80年代初期開發,利用這種格式,即使使用者沒有排版和程序設計的知識也可以充分發揮由TeX所提供的強大功能,能在幾天,甚至幾小時內生成很多具有書籍質量的印刷品。 你可以在...
閱讀全文
posted @
2013-02-16 13:51 Seraphi 閱讀(266) |
評論 (0) |
編輯 收藏
Python正則
初學Python,對Python的文字處理能力有很深的印象,除了str對象自帶的一些方法外,就是正則表達式這個強大的模塊了。但是對于初學者來說,要用好這個功能還是有點難度
,我花了好長時間才摸出了點門道。由于我記性不好,很容易就忘事,所以還是寫下來比較好一些,同時也可以加深印象,整理思路。
由于我是初學,所以肯定會有些錯誤,還望高手不吝賜教,指出我的錯誤。
1 Python正則式的基本用法
Python的正則表達式的模塊是‘re’,它的基本語法規則就是指定一個字符序列,比如你要在一個字符串s=’123abc456’中查找字符串’abc’,只要這樣寫:
>>> import re
>>> s='123abc456eabc789'
>>> re.findall(r’abc’,s)
結果就是:
['abc', 'abc']
這里用到的函數”findall(rule , target [,flag] )” 是個比較直觀的函數,就是在目標字符串中查找符合規則的字符串。第一個參數是規則,第二個參數是目標字符串,后面
還可以跟一個規則選項(選項功能將在compile函數的說明中詳細說明)。返回結果結果是一個列表,中間存放的是符合規則的字符串。如果沒有符合規則的字符串被找到,就返
回一個空列表。
為什么要用r’ ..‘字符串(raw字符串)?由于正則式的規則也是由一個字符串定義的,而在正則式中大量使用轉義字符’/’,如果不用raw字符串,則在需要寫一個’/’的地
方,你必須得寫成’//’,那么在要從目標字符串中匹配一個’/’的時候,你就得寫上4個’/’成為’////’!這當然很麻煩,也不直觀,所以一般都使用r’’來定義規則字符
串。當然,某些情況下,可能不用raw字符串比較好。
以上是個最簡單的例子。當然實際中這么簡單的用法幾乎沒有意義。為了實現復雜的規則查找,re規定了若干語法規則。它們分為這么幾類:
功能字符: ‘.’ ‘*’ ‘+’ ‘|’ ‘?’ ‘^’ ‘$’ ‘/’等,它們有特殊的功能含義。特別是’/’字符,它是轉義引導符號,跟在它后面的字符一般有特殊的含義。
規則分界符: ‘[‘ ‘]’ ‘(’ ‘)’ ‘{‘ ‘}’等,也就是幾種括號了。
預定義轉義字符集:“/d” “/w” “/s” 等等,它們是以字符’/’開頭,后面接一個特定字符的形式,用來指示一個預定義好的含義。
其它特殊功能字符:’#’ ‘!’ ‘:’ ‘-‘等,它們只在特定的情況下表示特殊的含義,比如(?# …)就表示一個注釋,里面的內容會被忽略。
下面來一個一個的說明這些規則的含義,不過說明的順序并不是按照上面的順序來的,而是我認為由淺入深,由基本到復雜的順序來編排的。同時為了直觀,在說明的過程中盡量
多舉些例子以方便理解。
1.1基本規則
‘[‘ ‘]’字符集合設定符
首先說明一下字符集合設定的方法。由一對方括號括起來的字符,表明一個字符集合,能夠匹配包含在其中的任意一個字符。比如[abc123],表明字符’a’ ‘b’ ‘c’ ‘1’
‘2’ ‘3’都符合它的要求。可以被匹配。
在’[‘ ‘]’中還可以通過’-‘ 減號來指定一個字符集合的范圍,比如可以用[a-zA-Z]來指定所以英文字母的大小寫,因為英文字母是按照從小到大的順序來排的。你不可以
把大小的順序顛倒了,比如寫成[z-a]就不對了。
如果在’[‘ ‘]’里面的開頭寫一個‘^’ 號,則表示取非,即在括號里的字符都不匹配。如[^a-zA-Z]表明不匹配所有英文字母。但是如果‘^’不在開頭,則它就不再是表示
取非,而表示其本身,如[a-z^A-Z]表明匹配所有的英文字母和字符’^’。
‘|’ 或規則
將兩個規則并列起來,以‘|’連接,表示只要滿足其中之一就可以匹配。比如
[a-zA-Z]|[0-9]表示滿足數字或字母就可以匹配,這個規則等價于[a-zA-Z0-9]
注意:關于’|’要注意兩點:
第一, 它在’[‘ ‘]’之中不再表示或,而表示他本身的字符。如果要在’[‘ ‘]’外面表示一個’|’字符,必須用反斜杠引導,即’/|’ ;
第二, 它的有效范圍是它兩邊的整條規則,比如‘dog|cat’匹配的是‘dog’和’cat’,而不是’g’和’c’。如果想限定它的有效范圍,必需使用一個無捕獲組‘
(?: )’包起來。比如要匹配‘I have a dog’或’I have a cat’,需要寫成r’I have a (?:dog|cat)’,而不能寫成r’I have a dog|cat’
例
>>> s = ‘I have a dog , I have a cat’
>>> re.findall( r’I have a (?:dog|cat)’ , s )
['I have a dog', 'I have a cat'] #正如我們所要的
下面再看看不用無捕獲組會是什么后果:
>>> re.findall( r’I have a dog|cat’ , s )
['I have a dog', 'cat'] #它將’I have a dog’和’cat’當成兩個規則了
至于無捕獲組的使用,后面將仔細說明。這里先跳過。
‘.’ 匹配所有字符
匹配除換行符’/n’外的所有字符。如果使用了’S’選項,匹配包括’/n’的所有字符。
例:
>>> s=’123 /n456 /n789’
>>> findall(r‘.+’,s)
['123', '456', '789']
>>> re.findall(r‘.+’ , s , re.S)
['123/n456/n789']
‘^’和’$’匹配字符串開頭和結尾
注意’^’不能在‘[ ]’中,否則含意就發生變化,具體請看上面的’[‘ ‘]’說明。在多行模式下,它們可以匹配每一行的行首和行尾。具體請看后面compile函數說明的’M
’選項部分
‘/d’匹配數字
這是一個以’/’開頭的轉義字符,’/d’表示匹配一個數字,即等價于[0-9]
‘/D’匹配非數字
這個是上面的反集,即匹配一個非數字的字符,等價于[^0-9]。注意它們的大小寫。下面我們還將看到Python的正則規則中很多轉義字符的大小寫形式,代表互補的關系。這樣很
好記。
‘/w’匹配字母和數字
匹配所有的英文字母和數字,即等價于[a-zA-Z0-9]。
‘/W’匹配非英文字母和數字
即’/w’的補集,等價于[^a-zA-Z0-9]。
‘/s’匹配間隔符
即匹配空格符、制表符、回車符等表示分隔意義的字符,它等價于[ /t/r/n/f/v]。(注意最前面有個空格)
‘/S’匹配非間隔符
即間隔符的補集,等價于[^ /t/r/n/f/v]
‘/A’匹配字符串開頭
匹配字符串的開頭。它和’^’的區別是,’/A’只匹配整個字符串的開頭,即使在’M’模式下,它也不會匹配其它行的很首。
‘/Z’匹配字符串結尾
匹配字符串的結尾。它和’$’的區別是,’/Z’只匹配整個字符串的結尾,即使在’M’模式下,它也不會匹配其它各行的行尾。
例:
>>> s= '12 34/n56 78/n90'
>>> re.findall( r'^/d+' , s , re.M ) #匹配位于行首的數字
['12', '56', '90']
>>> re.findall( r’/A/d+’, s , re.M ) #匹配位于字符串開頭的數字
['12']
>>> re.findall( r'/d+$' , s , re.M ) #匹配位于行尾的數字
['34', '78', '90']
>>> re.findall( r’/d+/Z’ , s , re.M ) #匹配位于字符串尾的數字
['90']
‘/b’匹配單詞邊界
它匹配一個單詞的邊界,比如空格等,不過它是一個‘0’長度字符,它匹配完的字符串不會包括那個分界的字符。而如果用’/s’來匹配的話,則匹配出的字符串中會包含那個
分界符。
例:
>>> s = 'abc abcde bc bcd'
>>> re.findall( r’/bbc/b’ , s ) #匹配一個單獨的單詞‘bc’ ,而當它是其它單詞的一部分的時候不匹配
['bc'] #只找到了那個單獨的’bc’
>>> re.findall( r’/sbc/s’ , s ) #匹配一個單獨的單詞‘bc’
[' bc '] #只找到那個單獨的’bc’,不過注意前后有兩個空格,可能有點看不清楚
‘/B’匹配非邊界
和’/b’相反,它只匹配非邊界的字符。它同樣是個0長度字符。
接上例:
>>> re.findall( r’/Bbc/w+’ , s ) #匹配包含’bc’但不以’bc’為開頭的單詞
['bcde'] #成功匹配了’abcde’中的’bcde’,而沒有匹配’bcd’
‘(?:)’無捕獲組
當你要將一部分規則作為一個整體對它進行某些操作,比如指定其重復次數時,你需要將這部分規則用’(?:’ ‘)’把它包圍起來,而不能僅僅只用一對括號,那樣將得到絕對
出人意料的結果。
例:匹配字符串中重復的’ab’
>>> s=’ababab abbabb aabaab’
>>> re.findall( r’/b(?:ab)+/b’ , s )
['ababab']
如果僅使用一對括號,看看會是什么結果:
>>> re.findall( r’/b(ab)+/b’ , s )
['ab']
這是因為如果只使用一對括號,那么這就成為了一個組(group)。組的使用比較復雜,將在后面詳細講解。
‘(?# )’注釋
Python允許你在正則表達式中寫入注釋,在’(?#’ ‘)’之間的內容將被忽略。
(?iLmsux) 編譯選項指定
Python的正則式可以指定一些選項,這個選項可以寫在findall或compile的參數中,也可以寫在正則式里,成為正則式的一部分。這在某些情況下會便利一些。具體的選項含義請
看后面的compile函數的說明。
此處編譯選項’i’等價于IGNORECASE ,L 等價于 LOCAL ,m 等價于 MULTILINE,s等價于 DOTALL ,u等價于UNICODE , x 等價于 VERBOSE。
請注意它們的大小寫。在使用時可以只指定一部分,比如只指定忽略大小寫,可寫為‘(?i)’,要同時忽略大小寫并使用多行模式,可以寫為‘(?im)’。
另外要注意選項的有效范圍是整條規則,即寫在規則的任何地方,選項都會對全部整條正則式有效。
1.2重復
正則式需要匹配不定長的字符串,那就一定需要表示重復的指示符。Python的正則式表示重復的功能很豐富靈活。重復規則的一般的形式是在一條字符規則后面緊跟一個表示重復
次數的規則,已表明需要重復前面的規則一定的次數。重復規則有:
‘*’ 0或多次匹配
表示匹配前面的規則0次或多次。
‘+’ 1次或多次匹配
表示匹配前面的規則至少1次,可以多次匹配
例:匹配以下字符串中的前一部分是字母,后一部分是數字或沒有的變量名字
>>> s = ‘ aaa bbb111 cc22cc 33dd ‘
>>> re.findall( r’/b[a-z]+/d*/b’ , s ) #必須至少1個字母開頭,以連續數字結尾或沒有數字
['aaa', 'bbb111']
注意上例中規則前后加了表示單詞邊界的’/b’指示符,如果不加的話結果就會變成:
>>> re.findall( r’[a-z]+/d*’ , s )
['aaa', 'bbb111', 'cc22', 'cc', 'dd'] #把單詞給拆開了
大多數情況下這不是我們期望的結果。
‘?’ 0或1次匹配
只匹配前面的規則0次或1次。
例,匹配一個數字,這個數字可以是一個整數,也可以是一個科學計數法記錄的數字,比如123和10e3都是正確的數字。
>>> s = ‘ 123 10e3 20e4e4 30ee5 ‘
>>> re.findall( r’ /b/d+[eE]?/d*/b’ , s )
['123', '10e3']
它正確匹配了123和10e3,正是我們期望的。注意前后的’/b’的使用,否則將得到不期望的結果。
1.2.1 精確匹配和最小匹配
Python正則式還可以精確指定匹配的次數。指定的方式是
‘{m}’ 精確匹配m次
‘{m,n}’ 匹配最少m次,最多n次。(n>m)
如果你只想指定一個最少次數或只指定一個最多次數,你可以把另外一個參數空起來。比如你想指定最少3次,可以寫成{3,}(注意那個逗號),同樣如果只想指定最大為5次,可
以寫成{,5},也可以寫成{0,5}。
例尋找下面字符串中
a:3位數
b: 2位數到4位數
c: 5位數以上的數
d: 4位數以下的數
>>> s= ‘ 1 22 333 4444 55555 666666 ‘
>>> re.findall( r’/b/d{3}/b’ , s ) # a:3位數
['333']
>>> re.findall( r’/b/d{2,4}/b’ , s ) # b: 2位數到4位數
['22', '333', '4444']
>>> re.findall( r’/b/d{5,}/b’, s ) # c: 5位數以上的數
['55555', '666666']
>>> re.findall( r’/b/d{1,4}/b’ , s ) # 4位數以下的數
['1', '22', '333', '4444']
‘*?’ ‘+?’ ‘??’最小匹配
‘*’ ‘+’ ‘?’通常都是盡可能多的匹配字符。有時候我們希望它盡可能少的匹配。比如一個c語言的注釋‘/* part 1 */ /* part 2 */’,如果使用最大規則:
>>> s =r ‘/* part 1 */ code /* part 2 */’
>>> re.findall( r’//*.*/*/’ , s )
[‘/* part 1 */ code /* part 2 */’]
結果把整個字符串都包括進去了。如果把規則改寫成
>>> re.findall( r’//*.*?/*/’ , s ) #在*后面加上?,表示盡可能少的匹配
['/* part 1 */', '/* part 2 */']
結果正確的匹配出了注釋里的內容
1.3 前向界定與后向界定
有時候需要匹配一個跟在特定內容后面的或者在特定內容前面的字符串,Python提供一個簡便的前向界定和后向界定功能,或者叫前導指定和跟從指定功能。它們是:
‘(?<=…)’前向界定
括號中’…’代表你希望匹配的字符串的前面應該出現的字符串。
‘(?=…)’ 后向界定
括號中的’…’代表你希望匹配的字符串后面應該出現的字符串。
例:你希望找出c語言的注釋中的內容,它們是包含在’/*’和’*/’之間,不過你并不希望匹配的結果把’/*’和’*/’也包括進來,那么你可以這樣用:
>>> s=r’/* comment 1 */ code /* comment 2 */’
>>> re.findall( r’(?<=//*).+?(?=/*/)’ , s )
[' comment 1 ', ' comment 2 ']
注意這里我們仍然使用了最小匹配,以避免把整個字符串給匹配進去了。
要注意的是,前向界定括號中的表達式必須是常值,也即你不可以在前向界定的括號里寫正則式。比如你如果在下面的字符串中想找到被字母夾在中間的數字,你不可以用前向界
定:
例:
>>> s = ‘aaa111aaa , bbb222 , 333ccc ‘
>>> re.findall( r’(?<=[a-z]+)/d+(?=[a-z]+)' , s ) #錯誤的用法
它會給出一個錯誤信息:
error: look-behind requires fixed-width pattern
不過如果你只要找出后面接著有字母的數字,你可以在后向界定寫正則式:
>>> re.findall( r’/d+(?=[a-z]+)’, s )
['111', '333']
如果你一定要匹配包夾在字母中間的數字,你可以使用組(group)的方式
>>> re.findall (r'[a-z]+(/d+)[a-z]+' , s )
['111']
組的使用將在后面詳細講解。
除了前向界定前向界定和后向界定外,還有前向非界定和后向非界定,它的寫法為:
‘(?<!...)’前向非界定
只有當你希望的字符串前面不是’…’的內容時才匹配
‘(?!...)’后向非界定
只有當你希望的字符串后面不跟著’…’內容時才匹配。
接上例,希望匹配后面不跟著字母的數字
>>> re.findall( r’/d+(?!/w+)’ , s )
['222']
注意這里我們使用了/w而不是像上面那樣用[a-z],因為如果這樣寫的話,結果會是:
>>> re.findall( r’/d+(?![a-z]+)’ , s )
['11', '222', '33']
這和我們期望的似乎有點不一樣。它的原因,是因為’111’和’222’中的前兩個數字也是滿足這個要求的。因此可看出,正則式的使用還是要相當小心的,因為我開始就是這樣
寫的,看到結果后才明白過來。不過Python試驗起來很方便,這也是腳本語言的一大優點,可以一步一步的試驗,快速得到結果,而不用經過煩瑣的編譯、鏈接過程。也因此學習
Python就要多試,跌跌撞撞的走過來,雖然曲折,卻也很有樂趣。
1.4組的基本知識
上面我們已經看過了Python的正則式的很多基本用法。不過如果僅僅是上面那些規則的話,還是有很多情況下會非常麻煩,比如上面在講前向界定和后向界定時,取夾在字母中間
的數字的例子。用前面講過的規則都很難達到目的,但是用了組以后就很簡單了。
‘(‘’)’ 無命名組
最基本的組是由一對圓括號括起來的正則式。比如上面匹配包夾在字母中間的數字的例子中使用的(/d+),我們再回顧一下這個例子:
>>> s = ‘aaa111aaa , bbb222 , 333ccc ‘
>>> re.findall (r'[a-z]+(/d+)[a-z]+' , s )
['111']
可以看到findall函數只返回了包含在’()’中的內容,而雖然前面和后面的內容都匹配成功了,卻并不包含在結果中。
除了最基本的形式外,我們還可以給組起個名字,它的形式是
‘(?P<name>…)’命名組
‘(?P’代表這是一個Python的語法擴展’<…>’里面是你給這個組起的名字,比如你可以給一個全部由數字組成的組叫做’num’,它的形式就是’(?P<num>/d+)’。起了名字之
后,我們就可以在后面的正則式中通過名字調用這個組,它的形式是
‘(?P=name)’調用已匹配的命名組
要注意,再次調用的這個組是已被匹配的組,也就是說它里面的內容是和前面命名組里的內容是一樣的。
我們可以看更多的例子:請注意下面這個字符串各子串的特點。
>>> s='aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'
我們看看下面的正則式會返回什么樣的結果:
>>> re.findall( r'([a-z]+)/d+([a-z]+)' , s ) #找出中間夾有數字的字母
[('aaa', 'aaa'), ('fff', 'ggg')]
>>> re.findall( r '(?P<g1>[a-z]+)/d+(?P=g1)' , s ) #找出被中間夾有數字的前后同樣的字母
['aaa']
>>> re.findall( r'[a-z]+(/d+)([a-z]+)' , s ) #找出前面有字母引導,中間是數字,后面是字母的字符串中的中間的數字和后面的字母
[('111', 'aaa'), ('777', 'ggg')]
我們可以通過命名組的名字在后面調用已匹配的命名組,不過名字也不是必需的。
‘/number’ 通過序號調用已匹配的組
正則式中的每個組都有一個序號,序號是按組從左到右,從1開始的數字,你可以通過下面的形式來調用已匹配的組
比如上面找出被中間夾有數字的前后同樣的字母的例子,也可以寫成:
>>> re.findall( r’([a-z]+)/d+/1’ , s )
['aaa']
結果是一樣的。
我們再看一個例子
>>> s='111aaa222aaa111 , 333bbb444bb33'
>>> re.findall( r'(/d+)([a-z]+)(/d+)(/2)(/1)' , s ) #找出完全對稱的數字-字母-數字-字母-數字中的數字和字母
[('111', 'aaa', '222', 'aaa', '111')]
Python2.4以后的re模塊,還加入了一個新的條件匹配功能
‘(?(id/name)yes-pattern|no-pattern)’ 判斷指定組是否已匹配,執行相應的規則
這個規則的含義是,如果id/name指定的組在前面匹配成功了,則執行yes-pattern的正則式,否則執行no-pattern的正則式。
舉個例子,比如要匹配一些形如usr@mail的郵箱地址,不過有的寫成< usr@mail >即用一對<>括起來,有點則沒有,要匹配這兩種情況,可以這樣寫
>>> s='<usr1@mail1> usr2@maill2'
>>> re.findall( r'(<)?/s*(/w+@/w+)/s*(?(1)>)' , s )
[('<', 'usr1@mail1'), ('', 'usr2@maill2')]
不過如果目標字符串如下
>>> s='<usr1@mail1> usr2@maill2 <usr3@mail3 usr4@mail4> < usr5@mail5 '
而你想得到要么由一對<>包圍起來的一個郵件地址,要么得到一個沒有被<>包圍起來的地址,但不想得到一對<>中間包圍的多個地址或不完整的<>中的地址,那么使用這個式子并
不能得到你想要的結果
>>> re.findall( r'(<)?/s*(/w+@/w+)/s*(?(1)>)' , s )
[('<', 'usr1@mail1'), ('', 'usr2@maill2'), ('', 'usr3@mail3'), ('', 'usr4@mail4'), ('', 'usr5@mail5')]
它仍然找到了所有的郵件地址。
想要實現這個功能,單純的使用findall有點吃力,需要使用其它的一些函數,比如match或search函數,再配合一些控制功能。這部分的內容將在下面詳細講解。
小結:以上基本上講述了Python正則式的語法規則。雖然大部分語法規則看上去都很簡單,可是稍不注意,仍然會得到與期望大相徑庭的結果,所以要寫好正則式,需要仔細的體
會正則式規則的含義后不同規則之間細微的差別。
詳細的了解了規則后,再配合后面就要介紹的功能函數,就能最大的發揮正則式的威力了。
2 re模塊的基本函數
在上面的說明中,我們已經對re模塊的基本函數‘findall’很熟悉了。當然如果光有findall的話,很多功能是不能實現的。下面開始介紹一下re模塊其它的常用基本函數。靈活
搭配使用這些函數,才能充分發揮Python正則式的強大功能。
首先還是說下老熟人findall函數吧
findall(rule , target [,flag] )
在目標字符串中查找符合規則的字符串。
第一個參數是規則,第二個參數是目標字符串,后面還可以跟一個規則選項(選項功能將在compile函數的說明中詳細說明)。
返回結果結果是一個列表,中間存放的是符合規則的字符串。如果沒有符合規則的字符串被找到,就返回一個空列表。
2.1使用compile加速
compile( rule [,flag] )
將正則規則編譯成一個Pattern對象,以供接下來使用。
第一個參數是規則式,第二個參數是規則選項。
返回一個Pattern對象
直接使用findall ( rule , target )的方式來匹配字符串,一次兩次沒什么,如果是多次使用的話,由于正則引擎每次都要把規則解釋一遍,而規則的解釋又是相當費時間的,
所以這樣的效率就很低了。如果要多次使用同一規則來進行匹配的話,可以使用re.compile函數來將規則預編譯,使用編譯過返回的Regular Expression Object或叫做Pattern對
象來進行查找。
例
>>> s='111,222,aaa,bbb,ccc333,444ddd'
>>> rule=r’/b/d+/b’
>>> compiled_rule=re.compile(rule)
>>> compiled_rule.findall(s)
['111', '222']
可見使用compile過的規則使用和未編譯的使用很相似。compile函數還可以指定一些規則標志,來指定一些特殊選項。多個選項之間用’|’(位或)連接起來。
I IGNORECASE 忽略大小寫區別。
L LOCAL 字符集本地化。這個功能是為了支持多語言版本的字符集使用環境的,比如在轉義符/w,在英文環境下,它代表[a-zA-Z0-9],即所以英文字符和數字。如果在一個法
語環境下使用,缺省設置下,不能匹配"é"或"ç"。加上這L選項和就可以匹配了。不過這個對于中文環境似乎沒有什么用,它仍然不能匹配中文字符。
M MULTILINE 多行匹配。在這個模式下’^’(代表字符串開頭)和’$’(代表字符串結尾)將能夠匹配多行的情況,成為行首和行尾標記。比如
>>> s=’123 456/n789 012/n345 678’
>>> rc=re.compile(r’^/d+’) #匹配一個位于開頭的數字,沒有使用M選項
>>> rc.findall(s)
['123'] #結果只能找到位于第一個行首的’123’
>>> rcm=re.compile(r’^/d+’,re.M) #使用M選項
>>> rcm.findall(s)
['123', '789', '345'] #找到了三個行首的數字
同樣,對于’$’來說,沒有使用M選項,它將匹配最后一個行尾的數字,即’678’,加上以后,就能匹配三個行尾的數字456 012和678了.
>>> rc=re.compile(r’/d+$’)
>>> rcm=re.compile(r’/d+$’,re.M)
>>> rc.findall(s)
['678']
>>> rcm.findall(s)
['456', '012', '678']
S DOTALL ‘.’號將匹配所有的字符。缺省情況下’.’匹配除換行符’/n’外的所有字符,使用這一選項以后,’.’就能匹配包括’/n’的任何字符了。
U UNICODE /w,/W,/b,/B,/d,/D,/s和/S都將使用Unicode。
X VERBOSE 這個選項忽略規則表達式中的空白,并允許使用’#’來引導一個注釋。這樣可以讓你把規則寫得更美觀些。比如你可以把規則
>>> rc = re.compile(r"/d+|[a-zA-Z]+") #匹配一個數字或者單詞
使用X選項寫成:
>>> rc = re.compile(r""" # start a rule/d+ # number| [a-zA-Z]+ # word""", re.VERBOSE)在這個模式下,如果你想匹配一個空格,你必須
用'/ '的形式('/'后面跟一個空格)
2.2 match與search
match( rule , targetString [,flag] )
search( rule , targetString [,flag] )
(注:re的match與search函數同compile過的Pattern對象的match與search函數的參數是不一樣的。Pattern對象的match與search函數更為強大,是真正最常用的函數)
按照規則在目標字符串中進行匹配。
第一個參數是正則規則,第二個是目標字符串,第三個是選項(同compile函數的選項)
返回:若成功返回一個Match對象,失敗無返回
findall雖然很直觀,但是在進行更復雜的操作時,就有些力不從心了。此時更多的使用的是match和search函數。他們的參數和findall是一樣的,都是:
match( rule , targetString [,flag] )
search( rule , targetString [,flag] )
不過它們的返回不是一個簡單的字符串列表,而是一個MatchObject(如果匹配成功的話).。通過操作這個matchObject,我們可以得到更多的信息。
需要注意的是,如果匹配不成功,它們則返回一個NoneType。所以在對匹配完的結果進行操作之前,你必需先判斷一下是否匹配成功了,比如:
>>> m=re.match( rule , target )
>>> if m: #必需先判斷是否成功
doSomethin
這兩個函數唯一的區別是:match從字符串的開頭開始匹配,如果開頭位置沒有匹配成功,就算失敗了;而search會跳過開頭,繼續向后尋找是否有匹配的字符串。針對不同的需
要,可以靈活使用這兩個函數。
關于match返回的MatchObject如果使用的問題,是Python正則式的精髓所在,它與組的使用密切相關。我將在下一部分詳細講解,這里只舉個最簡單的例子:
例:
>>> s= 'Tom:9527 , Sharry:0003'
>>> m=re.match( r'(?P<name>/w+):(?P<num>/d+)' , s )
>>> m.group()
'Tom:9527'
>>> m.groups()
('Tom', '9527')
>>> m.group(‘name’)
'Tom'
>>> m.group(‘num’)
'9527'
2.3 finditer
finditer( rule , target [,flag] )
參數同findall
返回一個迭代器
finditer函數和findall函數的區別是,findall返回所有匹配的字符串,并存為一個列表,而finditer則并不直接返回這些字符串,而是返回一個迭代器。關于迭代器,解釋起來
有點復雜,還是看看例子把:
>>> s=’111 222 333 444’
>>> for i in re.finditer(r’/d+’ , s ):
print i.group(),i.span() #打印每次得到的字符串和起始結束位置
結果是
111 (0, 3)
222 (4, 7)
333 (8, 11)
444 (12, 15)
簡單的說吧,就是finditer返回了一個可調用的對象,使用for i in finditer()的形式,可以一個一個的得到匹配返回的Match對象。這在對每次返回的對象進行比較復雜的操作
時比較有用。
2.4字符串的替換和修改
re模塊還提供了對字符串的替換和修改函數,他們比字符串對象提供的函數功能要強大一些。這幾個函數是
sub ( rule , replace , target [,count] )
subn(rule , replace , target [,count] )
在目標字符串中規格規則查找匹配的字符串,再把它們替換成指定的字符串。你可以指定一個最多替換次數,否則將替換所有的匹配到的字符串。
第一個參數是正則規則,第二個參數是指定的用來替換的字符串,第三個參數是目標字符串,第四個參數是最多替換次數。
這兩個函數的唯一區別是返回值。
sub返回一個被替換的字符串
sub返回一個元組,第一個元素是被替換的字符串,第二個元素是一個數字,表明產生了多少次替換。
例,將下面字符串中的’dog’全部替換成’cat’
>>> s=’ I have a dog , you have a dog , he have a dog ‘
>>> re.sub( r’dog’ , ‘cat’ , s )
' I have a cat , you have a cat , he have a cat '
如果我們只想替換前面兩個,則
>>> re.sub( r’dog’ , ‘cat’ , s , 2 )
' I have a cat , you have a cat , he have a dog '
或者我們想知道發生了多少次替換,則可以使用subn
>>> re.subn( r’dog’ , ‘cat’ , s )
(' I have a cat , you have a cat , he have a cat ', 3)
split( rule , target [,maxsplit] )
切片函數。使用指定的正則規則在目標字符串中查找匹配的字符串,用它們作為分界,把字符串切片。
第一個參數是正則規則,第二個參數是目標字符串,第三個參數是最多切片次數
返回一個被切完的子字符串的列表
這個函數和str對象提供的split函數很相似。舉個例子,我們想把上例中的字符串被’,’分割開,同時要去掉逗號前后的空格
>>> s=’ I have a dog , you have a dog , he have a dog ‘
>>> re.split( ‘/s*,/s*’ , s )
[' I have a dog', 'you have a dog', 'he have a dog ']
結果很好。如果使用str對象的split函數,則由于我們不知道’,’兩邊會有多少個空格,而不得不對結果再進行一次處理。
escape( string )
這是個功能比較古怪的函數,它的作用是將字符串中的non-alphanumerics字符(我已不知道該怎么翻譯比較好了)用反義字符的形式顯示出來。有時候你可能希望在正則式中匹
配一個字符串,不過里面含有很多re使用的符號,你要一個一個的修改寫法實在有點麻煩,你可以使用這個函數,
例在目標字符串s中匹配’(*+?)’這個子字符串
>>> s= ‘111 222 (*+?) 333’
>>> rule= re.escape( r’(*+?)’ )
>>> print rule
/(/*/+/?/)
>>> re.findall( rule , s )
['(*+?)']
3 更深入的了解re的組與對象
前面對Python正則式的組進行了一些簡單的介紹,由于還沒有介紹到match對象,而組又是和match對象密切相關的,所以必須將它們結合起來介紹才能充分地說明它們的用途。
不過再詳細介紹它們之前,我覺得有必要先介紹一下將規則編譯后的生成的patter對象
3.1編譯后的Pattern對象
將一個正則式,使用compile函數編譯,不僅是為了提高匹配的速度,同時還能使用一些附加的功能。編譯后的結果生成一個Pattern對象,這個對象里面有很多函數,他們看起來
和re模塊的函數非常象,它同樣有findall , match , search ,finditer , sub , subn , split這些函數,只不過它們的參數有些小小的不同。一般說來,re模塊函數的第一個
參數,即正則規則不再需要了,應為規則就包含在Pattern對象中了,編譯選項也不再需要了,因為已經被編譯過了。因此re模塊中函數的這兩個參數的位置,就被后面的參數取
代了。
findall , match , search和finditer這幾個函數的參數是一樣的,除了少了規則和選項兩個參數外,它們又加入了另外兩個參數,它們是:查找開始位置和查找結束位置,也就
是說,現在你可以指定查找的區間,除去你不感興趣的區間。它們現在的參數形式是:
findall ( targetString [, startPos [,endPos] ] )
finditer ( targetString [, startPos [,endPos] ] )
match ( targetString [, startPos [,endPos] ] )
search ( targetString [, startPos [,endPos] ] )
這些函數的使用和re模塊的同名函數使用完全一樣。所以就不多介紹了。
除了和re模塊的函數同樣的函數外,Pattern對象還多了些東西,它們是:
flags 查詢編譯時的選項
pattern查詢編譯時的規則
groupindex規則里的組
這幾個不是函數,而是一個值。它們提供你一些規則的信息。比如下面這個例子
>>> p=re.compile( r'(?P<word>/b[a-z]+/b)|(?P<num>/b/d+/b)|(?P<id>/b[a-z_]+/w*/b)' , re.I )
>>> p.flags
2
>>> p.pattern
'(?P<word>//b[a-z]+//b)|(?P<num>//b//d+//b)|(?P<id>//b[a-z_]+//w*//b)'
>>> p.groupindex
{'num': 2, 'word': 1, 'id': 3}
我們來分析一下這個例子:這個正則式是匹配單詞、或數字、或一個由字母或’_’開頭,后面接字母或數字的一個ID。我們給這三種情況的規則都包入了一個命名組,分別命名
為’word’ , ‘num’和‘id’。我們規定大小寫不敏感,所以使用了編譯選項‘I’。
編譯以后返回的對象為p,通過p.flag我們可以查看編譯時的選項,不過它顯示的不是’I’,而是一個數值2。其實re.I是一個整數,2就是它的值。我們可以查看一下:
>>> re.I
2
>>> re.L
4
>>> re.M
8
…
每個選項都是一個數值。
通過p.pattern可以查看被編譯的規則是什么。使用print的話會更好看一些
>>> print p.pattern
(?P<word>/b[a-z]+/b)|(?P<num>/b/d+/b)|(?P<id>/b[a-z_]+/w*/b)
看,和我們輸入的一樣。
接下來的p.groupindex則是一個字典,它包含了規則中的所有命名組。字典的key是名字,values是組的序號。由于字典是以名字作為key,所以一個無命名的組不會出現在這里。
3.2組與Match對象
組與Match對象是Python正則式的重點。只有掌握了組和Match對象的使用,才算是真正學會了Python正則式。
3.2.1 組的名字與序號
正則式中的每個組都有一個序號,它是按定義時從左到右的順序從1開始編號的。其實,re的正則式還有一個0號組,它就是整個正則式本身。
我們來看個例子
>>> p=re.compile( r’(?P<name>[a-z]+)/s+(?P<age>/d+)/s+(?P<tel>/d+).*’ , re.I )
>>> p.groupindex
{'age': 2, 'tel': 3, 'name': 1}
>>> s=’Tom 24 88888888 <=’
>>> m=p.search(s)
>>> m.groups() #看看匹配的各組的情況
('Tom', '24', '8888888')
>>> m.group(‘name’) #使用組名獲取匹配的字符串
‘Tom’
>>> m.group( 1 ) #使用組序號獲取匹配的字符串,同使用組名的效果一樣
>>> m.group(0) # 0組里面是什么呢?
'Tom 24 88888888 <='
原來0組就是整個正則式,包括沒有被包圍到組里面的內容。當獲取0組的時候,你可以不寫這個參數。m.group(0)和m.group()的效果是一樣的:
>>> m.group()
'Tom 24 88888888 <='
接下來看看更多的Match對象的方法,看看我們能做些什么。
3.2.2 Match對象的方法
group([index|id]) 獲取匹配的組,缺省返回組0,也就是全部值
groups() 返回全部的組
groupdict() 返回以組名為key,匹配的內容為values的字典
接上例:
>>> m.groupindex()
{'age': '24', 'tel': '88888888', 'name': 'Tom'}
start( [group] ) 獲取匹配的組的開始位置
end( [group] ) 獲取匹配的組的結束位置
span( [group] ) 獲取匹配的組的(開始,結束)位置
expand( template )根據一個模版用找到的內容替換模版里的相應位置
這個功能比較有趣,它根據一個模版來用匹配到的內容替換模版中的相應位置,組成一個新的字符串返回。它使用/g<index|name>或/index來指示一個組。
接上例
>>> m.expand(r'name is /g<1> , age is /g<age> , tel is /3')
'name is Tom , age is 24 , tel is 88888888'
除了以上這些函數外,Match對象還有些屬性
pos 搜索開始的位置參數
endpos 搜索結束的位置參數
這兩個是使用findall或match等函數時,傳入的參數。在上面這個例子里,我們沒有指定開始和結束位置,那么缺省的開始位置就是0,結束位置就是最后。
>>> m.pos
0
>>> m.endpos
19
lastindex 最后匹配的組的序號
>>> m.lastindex
3
lastgroup 最后匹配的組名
>>> m.lastgroup
'tel'
re 產生這個匹配的Pattern對象,可以認為是個逆引用
>>> m.re.pattern
'(?P<name>[a-z]+)//s+(?P<age>//d+)//s+(?P<tel>//d+).*'
得到了產生這個匹配的規則
string 匹配的目標字符串
>>> m.string
'Tom 24 88888888 <='
轉自:
http://hi.baidu.com/yangdaming1983/item/e6a8146255a5442169105b91
posted @
2013-02-11 16:28 Seraphi 閱讀(278) |
評論 (0) |
編輯 收藏
摘要: 1 概述1.1 什么是捕獲組捕獲組就是把正則表達式中子表達式匹配的內容,保存到內存中以數字編號或顯式命名的組里,方便后面引用。當然,這種引用既可以是在正則表達式內部,也可以是在正則表達式外部。捕獲組有兩種形式,一種是普通捕獲組,另一種是命名捕獲組,...
閱讀全文
posted @
2013-02-11 16:26 Seraphi 閱讀(1952) |
評論 (0) |
編輯 收藏
Python讀寫文件
1.open
使用open打開文件后一定要記得調用文件對象的close()方法。比如可以用try/finally語句來確保最后能關閉文件。
file_object = open('thefile.txt')
try:
all_the_text = file_object.read( )
finally:
file_object.close( )
注:不能把open語句放在try塊里,因為當打開文件出現異常時,文件對象file_object無法執行close()方法。
2.讀文件
讀文本文件
input = open('data', 'r')
#第二個參數默認為r
input = open('data')
讀二進制文件
input = open('data', 'rb')
讀取所有內容
file_object = open('thefile.txt')
try:
all_the_text = file_object.read( )
finally:
file_object.close( )
讀固定字節
file_object = open('abinfile', 'rb')
try:
while True:
chunk = file_object.read(100)
if not chunk:
break
do_something_with(chunk)
finally:
file_object.close( )
讀每行
list_of_all_the_lines = file_object.readlines( )
如果文件是文本文件,還可以直接遍歷文件對象獲取每行:
for line in file_object:
process line
3.寫文件
寫文本文件
output = open('data', 'w')
寫二進制文件
output = open('data', 'wb')
追加寫文件
output = open('data', 'w+')
寫數據
file_object = open('thefile.txt', 'w')
file_object.write(all_the_text)
file_object.close( )
寫入多行
file_object.writelines(list_of_text_strings)
注意,調用writelines寫入多行在性能上會比使用write一次性寫入要高。
在處理日志文件的時候,常常會遇到這樣的情況:日志文件巨大,不可能一次性把整個文件讀入到內存中進行處理,例如需要在一臺物理內存為 2GB 的機器上處理一個 2GB 的日志文件,我們可能希望每次只處理其中 200MB 的內容。
在 Python 中,內置的 File 對象直接提供了一個 readlines(sizehint) 函數來完成這樣的事情。以下面的代碼為例:
file = open('test.log', 'r')sizehint = 209715200 # 200Mposition = 0lines = file.readlines(sizehint)while not file.tell() - position < 0: position = file.tell() lines = file.readlines(sizehint)
每次調用 readlines(sizehint) 函數,會返回大約 200MB 的數據,而且所返回的必然都是完整的行數據,大多數情況下,返回的數據的字節數會稍微比 sizehint 指定的值大一點(除最后一次調用 readlines(sizehint) 函數的時候)。通常情況下,Python 會自動將用戶指定的 sizehint 的值調整成內部緩存大小的整數倍。
file在python是一個特殊的類型,它用于在python程序中對外部的文件進行操作。在python中一切都是對象,file也不例外,file有file的方法和屬性。下面先來看如何創建一個file對象:
file(name[, mode[, buffering]])
file()函數用于創建一個file對象,它有一個別名叫open(),可能更形象一些,它們是內置函數。來看看它的參數。它參數都是以字符串的形式傳遞的。name是文件的名字。
mode是打開的模式,可選的值為r w a U,分別代表讀(默認) 寫 添加支持各種換行符的模式。用w或a模式打開文件的話,如果文件不存在,那么就自動創建。此外,用w模式打開一個已經存在的文件時,原有文件的內容會被清空,因為一開始文件的操作的標記是在文件的開頭的,這時候進行寫操作,無疑會把原有的內容給抹掉。由于歷史的原因,換行符在不同的系統中有不同模式,比如在 unix中是一個\n,而在windows中是‘\r\n’,用U模式打開文件,就是支持所有的換行模式,也就說‘\r’ '\n' '\r\n'都可表示換行,會有一個tuple用來存貯這個文件中用到過的換行符。不過,雖說換行有多種模式,讀到python中統一用\n代替。在模式字符的后面,還可以加上+ b t這兩種標識,分別表示可以對文件同時進行讀寫操作和用二進制模式、文本模式(默認)打開文件。
buffering如果為0表示不進行緩沖;如果為1表示進行“行緩沖“;如果是一個大于1的數表示緩沖區的大小,應該是以字節為單位的。
file對象有自己的屬性和方法。先來看看file的屬性。
closed #標記文件是否已經關閉,由close()改寫
encoding #文件編碼
mode #打開模式
name #文件名
newlines #文件中用到的換行模式,是一個tuple
softspace #boolean型,一般為0,據說用于print
file的讀寫方法:
F.read([size]) #size為讀取的長度,以byte為單位
F.readline([size])
#讀一行,如果定義了size,有可能返回的只是一行的一部分
F.readlines([size])
#把文件每一行作為一個list的一個成員,并返回這個list。其實它的內部是通過循環調用readline()來實現的。如果提供size參數,size是表示讀取內容的總長,也就是說可能只讀到文件的一部分。
F.write(str)
#把str寫到文件中,write()并不會在str后加上一個換行符
F.writelines(seq)
#把seq的內容全部寫到文件中。這個函數也只是忠實地寫入,不會在每行后面加上任何東西。
file的其他方法:
F.close()
#關閉文件。python會在一個文件不用后自動關閉文件,不過這一功能沒有保證,最好還是養成自己關閉的習慣。如果一個文件在關閉后還對其進行操作會產生ValueError
F.flush()
#把緩沖區的內容寫入硬盤
F.fileno()
#返回一個長整型的”文件標簽“
F.isatty()
#文件是否是一個終端設備文件(unix系統中的)
F.tell()
#返回文件操作標記的當前位置,以文件的開頭為原點
F.next()
#返回下一行,并將文件操作標記位移到下一行。把一個file用于for ... in file這樣的語句時,就是調用next()函數來實現遍歷的。
F.seek(offset[,whence])
#將文件打操作標記移到offset的位置。這個offset一般是相對于文件的開頭來計算的,一般為正數。但如果提供了whence參數就不一定了,whence可以為0表示從頭開始計算,1表示以當前位置為原點計算。2表示以文件末尾為原點進行計算。需要注意,如果文件以a或a+的模式打開,每次進行寫操作時,文件操作標記會自動返回到文件末尾。
F.truncate([size])
#把文件裁成規定的大小,默認的是裁到當前文件操作標記的位置。如果size比文件的大小還要大,依據系統的不同可能是不改變文件,也可能是用0把文件補到相應的大小,也可能是以一些隨機的內容加上去。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/adupt/archive/2009/08/11/4435615.aspx
posted @
2013-02-10 23:31 Seraphi 閱讀(1312) |
評論 (0) |
編輯 收藏
posted @
2013-02-02 16:01 Seraphi 閱讀(361) |
評論 (0) |
編輯 收藏
linux 下的iconv命令可以把Windows默認GBK編碼的文件轉成Linux下用的UTF-8編碼。
Example: $ iconv -f GBK -t UTF-8 file_name -o file_name
1. 安裝命令行版的texlive: sudo apt-get install texlive-full
2. 安裝一個比較有幫助性的編輯器: sudo apt-get install texmaker
3. 安裝中文環境: sudo apt-get install latex-cjk-all
A useful webiste http://chixi.an.blog.163.com/blog/static/29359272201262952120729/
To install/upgrade to TeX Live 2012:
- Open a terminal with Ctrl+Alt+T
Add the texlive-backports PPA by typing the below (enter your password when prompted):
sudo apt-add-repository ppa:texlive-backports/ppa
Then type:
sudo apt-get update
Installation:
If you are installing TeX Live for the first time, type:
sudo apt-get install texlive
If you already have TeX Live installed and are upgrading, type:
sudo apt-get upgrade
Warning: this will also upgrade all other packages on your Ubuntu system for which upgrades are available. If you do not wish to do this, please use the previous sudo apt-get install texlive
instead.
轉自:http://blog.csdn.net/lsg32/article/details/8058491
posted @
2013-02-02 15:27 Seraphi 閱讀(286) |
評論 (0) |
編輯 收藏
在新版本的UBUNTU里不支持WINDOWS的wubi安裝,要用如下方式:
Ubuntu 12.04 wubi的安裝
一、在12.04里,在Windows內安裝那個選項被禁用了,只能通過以下指令開啟,X為光驅盤符:
代碼:
X:\wubi.exe --force-wubi
posted @
2013-02-01 12:27 Seraphi 閱讀(257) |
評論 (0) |
編輯 收藏
1、學會latex
2、熟練python
3、NLP相關知識,主要是gibbs sampling;以及這學期所學到的東西
4、Deep learning
5、改論文
6、加強算法方面的練習
posted @
2013-01-17 00:24 Seraphi 閱讀(189) |
評論 (0) |
編輯 收藏
【招聘須知】 Facebook正在全球招聘,對中國頂尖大學的Engineering專業學生尤其歡迎。 具體職位信息可以在https://www.facebook.com/careers上找到,申請的時候一般都是選 擇Software Engineer (University Recruiting),Facebook的制度是并不預先定向你去 哪個組。在入職的第一個月統一進行培訓,培訓結束的兩周后進行統一的Team Selectio n,每個組的大Manager過來將自己的組做的東西,你可以和感興趣的組聊,雙向選擇后最 終決定去哪里。所以是很自由的文化,決定你去哪里的最重要的是Potential,而不是你 已經在這個area的experience,這也是FB的文化,希望培養每個Engineer成為多面手,對 任何問題的Fast learner。 【基本要求】 專業不限要求有限,可以分成兩個類,看看你符合哪一類 1. 第一類: - ACM/ICPC 區域銀牌以上,或者在大型比賽上得過不錯的名次(前15%),這里大型比賽 指包括NOIP, NOI, APOI,省級選拔賽,Topcoder, Google Code Jam, 百度之星,有道難 題等等 - 在以下公司有過實習經驗:Google, Microsoft Research Asia, Hulu, EMC/VMware, Microstrategy (這些公司只是在經驗范圍內實習生非常靠譜,并沒有對其他公司不尊重 的意思,只是接觸的不多而已,見諒) - 本科成績年級前10%,核心課程算法,數據結構,C++,離散,組合數學等等絕大部分為 優秀 - 頂級會議上發表一二作論文,頂級會議的定義是專業領域內公認的大會,例如IR/ML領 域的SIGIR, ICML, WWW, ICDM等等 以上符合任意一條的話,請聯系我 2. 第二類: - <Crack the Coding Interview> 從頭到尾詳細閱讀并且做完所有的例題和習題 - www.leetcode.com 全部做完所有的題 符合以上所有條件的,請聯系我,附上代碼 PS: CTCI書課后有答案,leetcode網上有不錯的人做了發表,比如 https://github.com/zwxxx/LeetCode https://github.com/anson627/leetcode 做的時候請不要參考,做完以后可以和參考答案對比改進,直接抄答案是沒有意義的,答 案只是幫你提高的工具。對于代碼的要求是,寫的塊,風格簡潔,易于理解 【聯系方式】 請發郵件到郵箱zhangchitc@gmail.com,附上簡單的自我介紹,并著名是符合上述哪些要 求,如果第二類請用zip壓縮包打包代碼附在附件中 BTW: 第一類滿足的話最終還是要將第二類里面的材料全部做了的。。。。 【面試過程】 職位都是美國總部,不排除可能外派海外Site,不過基本應該都是前者。在推薦以后一 周之內應該總部會安排工程師使用skype進行2到3輪電話面試,通過以后提供機票到美國 進行onsite面試。3到5輪不等。基本都是算法面試,在白板上寫程序。全程英文,不需要 英語標準考試成績,但是對基本的聽力和口語要求比較高,要能自由和工程師進行交流, 語法有問題的可以完全不用擔心 住宿和交通費用全包。 【注意事項】 - 理論上是可以推實習的,不過對中國學生來講實習不是很現實,本科生太忙,研究生完 全2、3個月在外面導師應該說不過去 - 基本沒有deadline,全年都可以聯系我,但是考慮到大陸學生過去的H1B簽證申請,如 果拿到offer需要在每年4月前遞交申請,所以最晚開始面試應該是2月,越快申請越好 - 因為FB在中國沒有公開的招聘渠道,所以請不要傳播本帖(雖然知道基本是白說,但是 希望至少本校的同學不要傳播出去)招聘的細節我不能說太多,接觸以后可以聊 - 滿足條件就請大膽申請,在整個過程中我都可以為大家提供幫助和建議。根據HR的反饋 來看本人的推薦還是挺靠譜的,目前為止有7位同學通過我的推薦成功拿到了offer,目測 很快在一周之內會達到10個
posted @
2013-01-11 00:24 Seraphi 閱讀(2280) |
評論 (2) |
編輯 收藏
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}]
@="Internet Explorer"
"InfoTip"="@C:\\WINDOWS\\system32\\zh-CN\\ieframe.dll.mui,-881"
"LocalizedString"="@C:\\WINDOWS\\system32\\zh-CN\\ieframe.dll.mui,-880"
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\DefaultIcon]
@="C:\\Program Files\\Internet Explorer\\iexplore.exe,-32528"
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\Shell\NoAddOns]
@="在沒有加載項的情況下啟動"
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\Shell\NoAddOns\Command]
@="C:\\Program Files\\Internet Explorer\\iexplore.exe about:NoAdd-ons"
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\Shell\Open]
@="打開(O)"
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\Shell\Open\Command]
@="C:\\Program Files\\Internet Explorer\\iexplore.exe"
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\Shell\屬性(R)]
@=""
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\Shell\屬性(R)\Command]
@="Rundll32.exe Shell32.dll,Control_RunDLL Inetcpl.cpl"
[HKEY_CLASSES_ROOT\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}\ShellFolder]
@=""
"Attributes"=dword:00000010
"HideFolderVerbs"=""
"WantsParseDisplayName"=""
"HideOnDesktopPerUser"=""
@="C:\\WINDOWS\\system32\\ieframe.dll,-190"
"HideAsDeletePerUser"=""
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}]
@="Internet Explorer"
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\{B416D21B-3B22-B6D4-BBD3-BBD452DB3D5B}]
@="Windows Media"
posted @
2013-01-06 15:13 Seraphi 閱讀(179) |
評論 (0) |
編輯 收藏
set tags=tags;
set backspace=indent,eol,start
set shiftwidth=4
set tabstop=4
set expandtab
set encoding=utf8
set fileencodings=utf8,gbk
set nocompatible "去掉討厭的有關vim一致性模式,避免以前版本的一些bug和局限.
set number "顯示行號.
set background=dark "背景顏色暗色.(我覺得不錯,保護眼睛.)
syntax on "語法高亮顯示.(這個肯定是要的.)
set history=50 "設置命令歷史記錄為50條.
set autoindent "使用自動對起,也就是把當前行的對起格式應用到下一行.
set smartindent "依據上面的對起格式,智能的選擇對起方式,對于類似C語言編.
set tabstop=4 "設置tab鍵為4個空格.
set shiftwidth=4 "設置當行之間交錯時使用4個空格
set showmatch "設置匹配模式,類似當輸入一個左括號時會匹配相應的那個右括號
set incsearch
"搜索選項.(比如,鍵入"/bo",光標自動找到第一個"bo"所在的位置.)hi Comment ctermfg=darkmagenta
hi String ctermfg=darkred
hi Number ctermfg=darkblue
"是否生成一個備份文件.(備份的文件名為原文件名加“~“后綴
"(我不喜歡這個備份設置,一般注釋掉.)
"if has(“vms.
" set nobackup
"else
" set backup
"endif
關于注釋字體顏色的修改,可以參考:http://blog.csdn.net/a670449625/article/details/48051249
posted @
2012-11-09 19:44 Seraphi 閱讀(193) |
評論 (0) |
編輯 收藏
http://www.coli.uni-saarland.de/~csporled/page.php?id=tools
這個站點列舉出了幾乎所有NLP和IR領域能夠直接使用的好用的工具包~
posted @
2012-10-29 10:25 Seraphi 閱讀(303) |
評論 (0) |
編輯 收藏
轉載自:cool shell,作者:陳皓
From:http://coolshell.cn/articles/7992.html
先說明一下,我不希望本文變成語言爭論貼。希望下面的文章能讓我們客觀理性地了解C++這個語言。(另,我覺得技術爭論不要停留在非黑即白的二元價值觀上,這樣爭論無非就是比誰的嗓門大,比哪一方的觀點強,毫無價值。我們應該多看看技術是怎么演進的,怎么取舍的。)
事由
周五的時候,我在我的微博上發了一個貼說了一下一個網友給我發來的C++程序的規范和內存管理寫的不是很好(后來我刪除了,因為當事人要求),我并非批判,只是想說明其實程序員是需要一些“疫苗”的,并以此想開一個“程序員疫苗的網站”,結果,@簡悅云風同學直接回復到:“不要用 C++ 直接用 C , 就沒那么多坑了。”就把這個事帶入了語言之爭。
我又發了一條微博:
@左耳朵耗子
: 說C++比C的坑更多的人我可以理解,但理性地思考一下。C語言的坑也不少啊,如果說C語言有90個坑,那么C++就是100個坑(另,我看很多人都把C語言上的坑也歸到了C++上來),但是C++你得到的東西更多,封裝,多態,繼承擴展,泛型編程,智能指針,……,你得到了500%東西,但卻只多了10%的坑,多值啊。
結果引來了更多的回復(只節選了一些言論):
- @淘寶褚霸也在微博里說:“自從5年前果斷扔掉C++,改用了ansi c后,我的生活質量大大提升,沒有各種坑坑我。”
- @Laruence在其微博里說: “我確實用不到, C語言靈活運用struct, 可以很好的滿足這些需求.//@左耳朵耗子: 封裝,繼承,多態,模板,智能指針,這也用不到?這也學院派?//@Laruence: 問題是, 這些東西我都用不到… C語言是工程師搞的, C++是學院派搞的”
那么,C++的坑真的多么?我還請大家理性地思考一下。
C++真的比C差嗎?
我們先來看一個圖——《各種程序員的嘴臟的對比》,從這個圖上看,C程序員比C++的程序員在注釋中使用fuck的字眼多一倍。這說明了什么?我個人覺得這說明C程序員沒有C++程序員淡定。

不要太糾結上圖,只是輕松一下,我沒那么無聊,讓我們來看點真正的論據。
相信用過C++的程序員知道,C++的很多特性主要就是解決C語言中的各種不完美和缺陷:(注:C89、C99中許多的改進正是從C++中所引進的)
- 用const/inline/template代替了宏,解決了C語言中宏的各種坑。
- 用const的類型解決了很多C語言中變量值莫名改變的問題。
- 用引用代替指針,解決了C語言中指針的各種坑。這個在Java里得到徹底地體現。
- 用強類型檢查和四種轉型,解決了C語言中亂轉型的各種坑。
- 用封裝(構造,析構,拷貝構造,賦值重載)解決了C語言中各種復制一個結構體(struct)或是一個數據結構(link, hashtable, list, array等)中淺拷貝的內存問題的各種坑。
- 用封裝讓你可以在成員變量加入getter/setter,而不會像C一樣只有文件級的封裝。
- 用函數重載、函數默認參數,解決了C中擴展一個函數搞出來像func2()之類的ugly的東西。
- 用繼承多態和RTTI解決了C中亂轉struct指針和使用函數指針的諸多讓代碼ugly的問題。
- 用RAII,智能指針的方式,解決了C語言中因為出現需要釋放資源的那些非常ugly的代碼的問題。
- 用OO和GP解決各種C語言中用函數指針,對指針亂轉型,及一大砣if-else搞出來的ugly的泛型。
(注意:上面我沒有提重載運算符和異常,前者寫出來的代碼并不易讀和易維護(參看《
恐怖的C++語言》后面的那個示例),坑也多,后者并不成熟(相對于Java的異常),但是我們需要知道try-catch這種方式比傳統的不斷地判斷函數返回值和errno形成的大量的if-else在代碼可讀性上要好很多)
上述的這些東西填了不知有多少的C語言編程和維護的坑。少用指針,多用引用,試試autoptr,用用封裝,繼承,多態和函數重載…… 你面對的坑只會比C少,不會多。
C++的坑有多少?
C++的坑真的不多,如果你能花兩到三周的時候讀一下《Effecitve C++》里的那50多個條款,你就知道C++里的坑并不多,而且,有很多條款告訴我們C++是怎么解決C的坑的。然后,你可以讀讀《Exceptional C++》和《More Exceptional C++》,你可以了解一下C++各種問題的解決方法和一些常見的經典錯誤。
當然,C++在解決了很多C語的坑的同時,也因為OO和泛型又引入了一些坑。消一些,加一些,我個人感覺上總體上只比C多10%左右吧。但是你有了開發速度更快,代碼更易讀,更易維護的500%的利益。
另外,不可否認的是,C++中的代碼出了錯誤,有時候很難搞,而且似乎用C++的人會覺得C++更容易出錯?我覺得主要是下面幾個原因:
- C和C++都沒學好,大多數人用C++寫C,所以,C的坑和C++的坑合并了。
- C++太靈活了,想怎么搞就怎么搞,所以,各種不經意地濫用和亂搞。
另外,C++的編譯對標準C++的實現各異,支持地也千差萬別,所以會有一些比較奇怪的問題,但是如果你一般用用C++的封裝,繼承,多態,以及namespace,const, refernece, inline, templete, overloap, autoptr,還有一些OO 模式,并不會出現奇怪的問題。
而對于STL中的各種坑,我覺得是程序員們還對GP(泛型編程)理解得還不夠,STL是泛型編程的頂級實踐!屬于是大師級的作品,一般人很難理解。必需承認STL寫出來的代碼和編譯錯誤的確相當復雜晦澀,太難懂了。這也是C++的一個詬病。
這和Linus說的一樣 —— “C++是一門很恐怖的語言,而比它更恐怖的是很多不合格的程序員在使用著它”。注意我飄紅了“很多不合格的程序員”!
我覺得C++并不適合初級程序員使用,C++只適合高級程序員使用(參看《21天學好C++》和《C++學習自信心曲線》),正如《Why C++》中說的,C++適合那些對開發維護效率和系統性能同時關注的高級程序員使用。
這就好像飛機一樣,開飛機很難,開飛機要注意的東西太多太多,對駕駛員的要求很高,但你不能說飛機這個工具很爛,開飛機的坑太多。(注:我這里并不是說C++是飛機,C是汽車,C++和C的差距,比飛機到汽車的差距少太多太多,這里主要是類比,我們對待C++語言的心態!)
C++的初衷
理解C++設計的最佳讀本是《C++演化和設計》,在這本書中Stroustrup說了些事:
1)Stroustrup對C是非常欣賞,實際上早期C++許多的工作是對于C的強化和凈化,并把完全兼容C作為強制性要求。C89、C99中許多的改進正是從C++中所引進。可見,Stroustrup對C語言的貢獻非常之大。今天不管你對C++怎么看,C++的確擴展和進化了C,對C造成了深遠的影響。
2)Stroustrup對于C的抱怨主要來源于兩個方面——在C++兼容C的過程中遇到了不少設計實現上的麻煩;以及守舊的K&R C程序員對Stroustrup的批評。很多人說C++的惡夢就是要去兼容于C,這并不無道理(Java就干的比C++徹底得多),但這并不是Stroustrup考慮的,Stroustrup一邊在使盡渾身解數來兼容C,另一方面在拼命地優化C。
3)Stroustrup在書中直接說,C++最大的競爭對手正是C,他的目的就是——C能做到的,C++也必須做到,而且要做的更好。大家覺得是不是做到了?有多少做到了,有多少還沒有做到?
4)對于同時關注的運行效率和開發效率的程序員,Stroustrup多次強調C++的目標是——“在保證效率與C語言相當的情況下,加強程序的組織性;能保證同樣功能的程序,C++更短小”,這正是淺封裝的核心思想。而不是過渡設計的OO。(參看:面向對象是個騙局)
5)這本書中舉了很多例子來回應那些批評C++有運行性能問題的人。C++在其第二個版本中,引入了虛函數機制,這是C++效率最大的瓶頸了,但我個人認為虛函數就是多了一次加法運算,但讓我們的代碼能有更好的組織,極大增加了程序的閱讀和降底了維護成本。(注:Lippman的《深入探索C++對象模型》也說明了C++不比C的程序在運行性能低。Bruce的《Think in C++》也說C++和C的性能相差只有5%)
6)這本書中還講了一些C++的痛苦的取舍,印象最深的就是多重繼承,提出,拿掉,再被提出,反復很多次,大家在得與失中不斷地辯論和取舍。這個過程讓我最大的收獲是——a) 對于任何一種設計都有好有壞,都只能偏重一方,b) 完全否定式的批評是不好的心態,好的心態應該是建設性地批評。
我對C++的感情
我先說說我學C++的經歷。
我畢業時,是直接從C跳過C++學Java的,但是學Java的時候,不知道為什么Java要設計成這樣,只好回頭看C++,結果學C++的時候又有很多不懂,又只得回頭看C,最后發現,C -> C++ -> Java的過程,就是C++填C的坑,Java填C++的坑的過程。
注,下面這些東西可以看到Java在填C/C++坑:
- Java徹底廢棄了指針(指針這個東西,絕對讓這個社會有幾百億的損失),使用引用。
- Java用GC解決了C++的各種內存問題的詬病,當然也帶來了GC的問題,不過功大于過。
- Java對異常的支持比C++更嚴格,讓編程更方便了。
- Java沒有像C++那樣的template/macro/函數對象/操作符重載,泛型太晦澀,用OO更容易一些。
- Java改進了C++的構造、析構、拷貝構造、賦值。
- Java對完全拋棄了C/C++這種面向過程的編程方式,并廢棄了多重繼承,更OO(如:用接口來代替多重繼承)
- Java比較徹底地解決了C/C++自稱多年的跨平臺技術。
- Java的反射機制把這個語言提升了一個高度,在這個上面可以構建各種高級用法。
- C/C++沒有一些比較好的類庫,比如UI,線程 ,I/O,字符串處理等。(C++0x補充了一些)
- 等等……
當然時代還在前進,這個演變的過程還在C#和Go上體現著。不過我學習了C -> C++ -> Java這個填坑演進的過程,讓我明白了很多東西:
- 我明白了OO是怎么一回事,重要的是明白了OO的封裝,繼承,和多態是怎么實現的。(參看我以前寫過的《C++虛函數表解析》和《C++對象內存布局》)
- 我明白了STL的泛型編程和Java的各種花哨的技術是怎么一回事,以及那些很花哨的編程方法和技術。
- 我明白了C,C++,Java的各中坑,這就好像玩火一樣,我知道怎么玩火不會燒身了。
我從這個學習過程中得到的最大的收獲不是語言本身,而是各式各樣的編程技術和方法,和技術的演進的過程,這比語言本身更重要!(在這個角度上學習,你看到的不是一個又一個的坑,你看到的是——各式各樣讓你可以爬得更高的梯子)
我對C++的感情有三個過程:先是喜歡地要死,然后是恨地要死,現在的又愛又恨,愛的是這個語言,恨的是很多不合格的人在濫用和凌辱它。
C++的未來
C++語言發展大概可以分為三個階段(摘自Wikipedia):
- 第一階段從80年代到1995年。這一階段C++語言基本上是傳統類型上的面向對象語言,并且憑借著接近C語言的效率,在工業界使用的開發語言中占據了相當大份額;
- 第二階段從1995年到2000年,這一階段由于標準模板庫(STL)和后來的Boost等程式庫的出現,泛型程式設計在C++中占據了越來越多的比重性。當然,同時由于Java、C#等語言的出現和硬件價格的大規模下降,C++受到了一定的沖擊;
- 第三階段從2000年至今,由于以Loki、MPL等程式庫為代表的產生式編程和模板元編程的出現,C++出現了發展歷史上又一個新的高峰,這些新技術的出現以及和原有技術的融合,使C++已經成為當今主流程式設計語言中最復雜的一員。
在《Why C++? 王者歸來》中說了 ,性能主要就是要省電,省電就是省錢,在數據中心還不明顯,在手機上就更明顯了,這就是為什么Android 支持C++的原因。所以,在NB的電池或是能源出現之前,如果你需要注重程序的運行性能和開發效率,并更關注程序的運性能,那么,應該首選 C++。這就是iOS開發也支持C++的原因。

今天的C++11中不但有更多更不錯的東西,而且,還填了更多原來C++的坑。(參看:C++11 Wiki,C++ 11的主要特性)

總結
- 是那些不合格的、想對編程速成的程序員讓C++變得坑多。
最后,非常感謝能和“@簡悅云風”,“@淘寶諸霸”,“@Laruence”一起討論這個問題!無論你們的觀點怎么樣,我都和你們“在一起”,嘿嘿嘿……
(全文完)
posted @
2012-08-06 12:58 Seraphi 閱讀(424) |
評論 (0) |
編輯 收藏
轉載Cool Shell,作者:陳皓
From:http://coolshell.cn/articles/2250.html
下面是一個《Teach Yourself C++ in 21 Days》的流程圖,請各位程序員同仁認真領會。如果有必要,你可以查看這個圖書以作參照:http://www.china-pub.com/27043

看完上面這個圖片,我在想,我學習C++有12年了,好像C++也沒有學得特別懂,看到STL和泛型,還是很頭大。不過,我應該去考慮研究量子物理和生物化學,這樣,我才能重返98年殺掉還在大學的我,然后達到21天搞定C++的目標。另外,得要特別提醒剛剛開始學習C++的朋友,第21天的時候,小心被人殺害。呵呵。
當然,上面只是一個惡搞此類圖片,學習一門技術,需要你很長的時間,正如圖片中的第三圖和第四圖所示,你需要用十年的時間去不斷在嘗試,并在錯誤中總結經驗教訓,以及在項目開發中通過與別人相互溝通互相學習來歷練自己。你才能算得上是真正學會。
這里有篇文章叫《Teach Yourself Programming in Ten Years》,網上有人翻譯了一下,不過原文已被更新了,我把網上的譯文轉載并更新如下:
用十年來學編程
Peter Norvig
為什么每個人都急不可耐?
走進任何一家書店,你會看見《Teach Yourself Java in 7 Days》(7天Java無師自通)的旁邊是一長排看不到盡頭的類似書籍,它們要教會你Visual Basic、Windows、Internet等等,而只需要幾天甚至幾小時。我在
Amazon.com上進行了如下
搜索:
結論是,要么是人們非常急于學會計算機,要么就是不知道為什么計算機驚人地簡單,比任何東西都容易學會。沒有一本書是要在幾天里教會人們欣賞貝多芬或者量子物理學,甚至怎樣給狗打扮。在《
How to Design Programs》這本書里說“
Bad programming is easy. Idiots can learn it in 21 days, even if they are dummies.” (壞的程序是很容易的,就算他們是笨蛋白癡都可以在21天內學會。)
- 學會:在3天時間里,你不夠時間寫一些有意義的程序,并從它們的失敗與成功中學習。你不夠時間跟一些有經驗的程序員一起工作,你不會知道在C++那樣的環境中是什么滋味。簡而言之,沒有足夠的時間讓你學到很多東西。所以這些書談論的只是表面上的精通,而非深入的理解。如Alexander Pope(英國詩人、作家,1688-1744)所言,一知半解是危險的(a little learning is a dangerous thing)
- C++:在3天時間里你可以學會C++的語法(如果你已經會一門類似的語言),但你無法學到多少如何運用這些語法。簡而言之,如果你是,比如說一個Basic程序員,你可以學會用C++語法寫出Basic風格的程序,但你學不到C++真正的優點(和缺點)。那關鍵在哪里?Alan Perlis(ACM第一任主席,圖靈獎得主,1922-1990)曾經說過:“如果一門語言不能影響你對編程的想法,那它就不值得去學”。另一種觀點是,有時候你不得不學一點C++(更可能是javascript和Flash Flex之類)的皮毛,因為你需要接觸現有的工具,用來完成特定的任務。但此時你不是在學習如何編程,你是在學習如何完成任務。
- 3天:不幸的是,這是不夠的,正如下一節所言。
10年學編程
在這三個小組中的每一個人基本上都是從相同的時間開始練習的(在五歲的時候)。在開始的幾年里,每個人都是每周練習2-3個小時。但是在八歲的時候,練習的強度開始顯現差異。在這個班中水平最牛的人開始比別人練習得更多——在九歲的時候每周練習6個小時,十二歲的時候,每周8個小時,十四歲的時候每周16個小時,并在成長過程中練習得越來越多,到20歲的時候,其每周練習可超過30個小時。到了20歲,這些優秀者在其生命中練習音樂總共超過 10,000 小時。與之對比,其它人只平均有8,000小時,而未來只能留校當老師的人僅僅是4,000 小時。
所以,這也許需要10,000 小時,并不是十年,但這是一個magic number。Samuel Johnson(英國詩人)認為10 年還是不夠的:“任何領域的卓越成就都只能通過一生的努力來獲得;稍低一點的代價也換不來。”(Excellence in any department can be attained only by the labor of a lifetime; it is not to be purchased at a lesser price.) 喬叟(Chaucer,英國詩人,1340-1400)也抱怨說:“生命如此短暫,掌握技藝卻要如此長久。”(the lyf so short, the craft so long to lerne.)
下面是我在編程這個行當里獲得成功的處方:
- 對編程感興趣,因為樂趣而去編程。確定始終都能保持足夠的樂趣,以致你能夠將10年時間投入其中。
- 跟其他程序員交談;閱讀其他程序。這比任何書籍或訓練課程都更重要。
- 編程。最好的學習是從實踐中學習。用更加技術性的語言來講,“個體在特定領域最高水平的表現不是作為長期的經驗的結果而自動獲得的,但即使是非常富有經驗的個體也可以通過刻意的努力而提高其表現水平。”(p. 366),而且“最有效的學習要求為特定個體制定適當難度的任務,有意義的反饋,以及重復及改正錯誤的機會。”(p. 20-21)《Cognition in Practice: Mind, Mathematics, and Culture in Everyday Life》(在實踐中認知:心智、數學和日常生活的文化)是關于這個觀點的一本有趣的參考書。
- 如果你愿意,在大學里花上4年時間(或者再花幾年讀研究生)。這能讓你獲得一些工作的入門資格,還能讓你對此領域有更深入的理解,但如果你不喜歡進學校,(作出一點犧牲)你在工作中也同樣能獲得類似的經驗。在任何情況下,單從書本上學習都是不夠的。“計算機科學的教育不會讓任何人成為內行的程序員,正如研究畫筆和顏料不會讓任何人成為內行的畫家”, Eric Raymond,《The New Hacker’s Dictionary》(新黑客字典)的作者如是說。我曾經雇用過的最優秀的程序員之一僅有高中學歷;但他創造出了許多偉大的軟件(XEmacs, Mozilla),甚至有討論他本人的新聞組,而且股票期權讓他達到我無法企及的富有程度(譯注:指Jamie Zawinski,Xemacs和Netscape的作者)。
- 跟別的程序員一起完成項目。在一些項目中成為最好的程序員;在其他一些項目中當最差的一個。當你是最好的程序員時,你要測試自己領導項目的能力,并通過你的洞見鼓舞其他人。當你是最差的時候,你學習高手們在做些什么,以及他們不喜歡做什么(因為他們讓你幫他們做那些事)。
- 接手別的程序員完成項目。用心理解別人編寫的程序。看看在沒有最初的程序員在場的時候理解和修改程序需要些什么。想一想怎樣設計你的程序才能讓別人接手維護你的程序時更容易一些。
- 學會至少半打編程語言。包括一門支持類抽象(class abstraction)的語言(如Java或C++),一門支持函數抽象(functional abstraction)的語言(如Lisp或ML),一門支持句法抽象(syntactic abstraction)的語言(如Lisp),一門支持說明性規約(declarative specification)的語言(如Prolog或C++模版),一門支持協程(coroutine)的語言(如Icon或Scheme),以及一門支持并行處理(parallelism)的語言(如Sisal)。
- 記住在“計算機科學”這個詞組里包含“計算機”這個詞。了解你的計算機執行一條指令要多長時間,從內存中取一個word要多長時間(包括緩存命中和未命中的情況),從磁盤上讀取連續的數據要多長時間,定位到磁盤上的新位置又要多長時間。(答案在這里)
- 嘗試參與到一項語言標準化工作中。可以是ANSI C++委員會,也可以是決定自己團隊的編碼風格到底采用2個空格的縮進還是4個。不論是哪一種,你都可以學到在這門語言中到底人們喜歡些什么,他們有多喜歡,甚至有可能稍微了解為什么他們會有這樣的感覺。
- 擁有盡快從語言標準化工作中抽身的良好判斷力。
抱著這些想法,我很懷疑從書上到底能學到多少東西。在我第一個孩子出生前,我讀完了所有“怎樣……”的書,卻仍然感到自己是個茫無頭緒的新手。30個月后,我第二個孩子出生的時候,我重新拿起那些書來復習了嗎?不。相反,我依靠我自己的經驗,結果比專家寫的幾千頁東西更有用更靠得住。
Fred Brooks在他的短文《No Silver Bullets》(沒有銀彈)中確立了如何發現杰出的軟件設計者的三步規劃:
- 盡早系統地識別出最好的設計者群體。
- 指派一個事業上的導師負責有潛質的對象的發展,小心地幫他保持職業生涯的履歷。
- 讓成長中的設計師們有機會互相影響,互相激勵。
這實際上是假定了有些人本身就具有成為杰出設計師的必要潛質;要做的只是引導他們前進。Alan Perlis說得更簡潔:“每個人都可以被教授如何雕塑;而對米開朗基羅來說,能教給他的倒是怎樣能夠不去雕塑。杰出的程序員也一樣”。
所以盡管去買那些Java書;你很可能會從中找到些用處。但你的生活,或者你作為程序員的真正的專業技術,并不會因此在24小時、24天甚至24個月內發生真正的變化。
(全文完)
posted @
2012-08-06 12:56 Seraphi 閱讀(349) |
評論 (0) |
編輯 收藏
注:如果看不到圖片,請右鍵圖片獲得圖片地址,然后在瀏覽中訪問圖片地址即可~
1.去下載LINUX上使用的BIN文件,去www.java.sun.com,最終會到ORACLE網站上去,因為SUN被收購了嘛,下載JDK,名稱為jdk-6u22-linux-i586.bin,然后去www.eclipse.org,下載eclipse,筆者下載的是JAVA EE版的,文件名稱為eclipse-jee-helios-SR1-linux-gtk.tar.gz,因為這個工具多,比較適合WEB等開發。路徑
2.本人的文件目錄放在/home/heroguo/下載,使用tar命令解壓(這個具體可以去查找資料或者tar -help)eclipse,會生成eclipse文件夾。mv到/home文件夾。
3、安裝JDK,使用終端,運行下載下來的jdk-6u22-linux-i586.bin。
第一步,將目錄CD到/home/heroguo/下載。
第二步,使用命令./jdk-6u22-linux-i586.bin,等待中,直到完成。完成后,會在當前目錄下生成一個JDK1.6.0_22的文件夾。
第三步,使用mv命令將JDK1.6.0_22到/home文件夾。
4.環境變量
用文本編輯器打開/etc/profile
·在profile文件末尾加入:
export JAVA_HOME=/usr/share/jdk1.6.0_14
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
注意:千萬不要范和筆者一樣的錯,狂暈,寫PATH的時候,前面的$PATH 沒有寫,導致PATH路徑下所有位置被覆蓋,包括寫命令都得打完整路徑,汗死!!路徑之間用:隔開
這一步很重要:重啟ubuntu,在終端中輸入java –version,查看版本號
看到上面按要求1.6.0_22證明JDK被正確安裝了
5.用終端將當前目錄CD為 /home/heroguo/eclipse,使用命令./eclipse,可以看到eclipse開始運行了。
彈出eclipse工作目錄設置,OK基本JAVA開發環境也搞定了。
進行WEB開發,再去下個TOMCAT,由于TOMCAT7 剛出來,所以選擇了TOMCAT6,方法和WINDOWS上一樣的,就不再贅述了,哈哈,休息哈去!
轉貼:原文鏈接:
http://blog.csdn.net/guoleimail/article/details/5960244
posted @
2012-05-10 12:09 Seraphi 閱讀(992) |
評論 (1) |
編輯 收藏
怎樣做研究(一)
幾年前,我寫了一套膠片,題目是《怎樣做研究》,多次在實驗室內部給學生們做報告,也曾對外講過一次,聽眾反應良好。也有網友讀過這套膠片,給我來信稱有所收獲。然而,膠片中的文字畢竟只是提綱攜領,無法充分闡述我的想法,為此,借周末一點閑暇,把《怎樣做研究》寫成一篇文章,與師友切磋。
什么是科學
科學是分科的學問,客觀地說,是起源于西方的。中國只有經驗科學,典型的如中醫。我的母親是學中醫的,我從小就對中醫耳濡目染,生了病,媽媽就會請他的老師來,一貼小藥下去,我的病就好了。因此,我對中醫一直是很信服的。然而,近些年來,中醫多受批評,發展也越來越緩慢,究其原因,中醫不是科學,或者說只是經驗科學,而非實證科學。中藥的成分以及生化功效不曾用實驗進行深入的分析,望聞問切的診斷方法完全憑經驗而無法量化,陰陽五行的理論似是而非,祖傳秘方的傳承方式與知識共享的現代思維背道而馳。因此,盡管中醫有診治的整體觀和方劑的個性化兩大優點,但其停留于經驗層面,而遲遲不能進入科學的殿堂,因此在現代社會中的發展必然步履維艱。
中醫不是科學,那到底什么是科學呢?科學(自然科學)是人們用來認識和改造自然世界的思維武器,科學研究可以分為基礎研究(理論研究)和應用研究(技術研發)。
基礎研究
萬事萬物皆有其規律,掌握并且利用這些規律就能夠為人類造福,這些規律是隱蔽在紛繁復雜的現象背后的,要識破大自然的奧秘,讀懂上帝的天書,非要下一番深入觀察和探究的功夫不可。以揭示規律為目的的研究活動屬于基礎研究,從事這些活動的學者是科學家。規律不是被創造出來的,而是早已存在的,人們只有認識規律的權利,而沒有創造規律的可能。
從根本上講,推動基礎研究的也是人們在生產生活中的一些實際需要,但是隨著基礎研究的深入,理論已經成為一個龐大的體系,理論研究早已開始按照它自有的邏輯獨立發展,而不必時時刻刻聯系實際需要,比如著名的歌德巴赫猜想,可能在百年之后,發現其有重大的應用價值,但是目前到底有什么用,誰也說不清楚。理論的價值在今天這個非常講求短期功利的社會中常常被忽視,現在有一種傾向認為只有產生實際經濟效益的科研工作才有價值,這種極端化的觀點顯然是錯誤的,我們必須承認并高度尊重理論研究者的成就。
理論研究的直接動力是科學家的好奇心,以及他們對科學榮譽的渴望。越是單純的科學家越有希望發現真理,他們的科學探索有點像迷宮探寶或者海邊拾貝,偉大的科學家都是沒有喪失童趣的人,他們在實驗室里是寧靜而愉快的,他們是樂此不疲的,很多在常人看來難以忍受的寂寞在他們看來卻是一種幸福。越是找不到答案,越是激發探索的熱情,在一次次的失敗中積累著煩悶與緊張,在終于取得突破后興奮異常。與此同時,也必須承認科學榮譽也是激勵科學家們前進的重要動力,只要別把榮譽看得高于真理,貨真價實的榮譽仍然是值得追求的。
理論上的突破對應用研究產生持續不斷的推動力,在模式識別領域,神經網絡、支持向量機、條件隨機域等等機器學習技術不斷出現,每當一項理論出現,應用研究者們爭相將其應用于自己的研究課題中,于是基于神經網絡、基于支持向量機、基于條件隨機域的某某研究就成為一個標準的論文題目。首先把某項理論應用于某個實際課題的研究工作應該說還是具有一定的創新性的,畢竟用一個新的思路、新的模型去觀察了一個舊的課題,HMM在語音識別上的成功應用就是一例。有人比喻說,理論工具仿佛是錘子,實際課題好比是釘子,一個新的錘子被打造出來,大家都借用過來砸一砸自己手頭的釘子,確屬常理。不過,需要注意的事,如果拿一個碩大無比的汽錘去砸一個纖細的大頭針就荒誕可笑了,不注意思考問題與理論的適配關系而盲目跟風的事情在學術界也是司空見慣,比如我們就曾用HMM試圖解決詞義消歧的問題,而每個多義詞的詞義跟它前后一兩個詞并沒有緊密的關系,因此詞義消歧貌似和詞性標注一樣屬于線性序列標注問題,其實是有根本差別的。
應用研究
我們是搞計算機的,計算機是一門應用科學,應用科學是由應用驅動的。時至今日,數學定理和物理學定律似乎已經被先哲們發現的差不多了,因此整個科學界中純粹搞理論研究的人越來越少,很多大學教授都和工業界有著密切的聯系,很多大企業也開辦企業研究院,這些導致應用科學的研究如火如荼。最近,國家863設立了一個"中文為核心的多語言信息處理"重點項目,總經費7000萬,這在多年前的大陸語言處理界完全是不可想象的。
應用驅動,也可以說是市場驅動。市場是一個精靈古怪的家伙,搞應用研究的人如果對市場的未來沒有一個基本準確地判斷,往往會導致選題上的偏差。二十年前,國內一些研究者開始研究漢字手寫輸入技術,開始人們覺得從鍵盤輸入漢字很困難,手寫輸入一定有前途,但是很快,拼音輸入法大面積普及,而且拼音輸入的速度遠比在手寫板上輸入漢字快得多,于是漢字手寫輸入套件根本賣不動,前景黯淡。有人開始猶豫,有人開始轉向搞印刷體漢字識別等,但忽然有一天,集成了手寫功能的商務通大量熱銷,人們忽然發現原來在手持設備上由于鍵盤太小,輸入不便,給手寫功能留下了很大的應用空間。一直專注于手寫識別的漢王公司也借著商務通的熱銷而把多年的科研成果成功地產業化了。再舉一個例子:5年前,我認為以圖像為輸入的圖像檢索沒有什么應用價值,問這些技術的倡導者,他們也只說能夠在數碼相冊中可以找到一些應用,但近來聽了微軟一些學者們的演講,他們提到可以用手機拍下一個植物的圖片,傳回服務器,在大量植物圖片庫中檢索,找到最相似的植物,并給出植物的名稱,特點等。哈哈,這對于我這個五谷不分的人來說實在是太有幫助了,可見對于一項技術是否有用實在要仔細思考,不要早下斷言。
技術和市場是一個互動的關系,有人認為技術嚴格地從用戶的現實需求出發,這個觀點總的來說沒有錯,但是忽視了技術創造需求的一面。大多數用戶往往并不了解技術發展到了什么程度,他們提不出需求來,這時技術專家們需要把技術和產品做出來給人們看,刺激、引領用戶的需求,比如數碼相機,5年前我想大多數用戶和我一樣并沒有淘汰膠卷相機的強烈要求,但當數碼相機進入市場后,人人都意識到:原來我需要這個東東。
在市場與技術的互動中,總的來說,還是市場在引導和拉動技術的發展。市場需要的是產品,產品往往集成了多項技術,因此一項被市場接受的產品能夠推動多項技術的進步。比如搜索引擎,它拉動了自然語言處理、并行計算、海量存儲設備、數據挖掘等等多項技術的發展。最近中國計算機學會設立了王選獎,在中國真正有市場眼光,能夠發明一項技術,拉動一個行業的計算機專家,王選是第一人。怎樣根據市場選擇研究方向,設計產品,調整技術形態,我在后面還有詳細闡述。
科學技術的力量
科學技術的力量是巨大的,愛因斯坦給出的公式E=M*C2,C是光速啊,質量乘以光速的平方,這是多么巨大的能量啊,愛因斯坦的理論直接導致了原子能的利用與開發。基因圖譜的發現以及后基因組時代對基因圖譜的深入分析必將為人類征服疾病提供一條嶄新的解決道路,通過對損壞的基因進行修復,將使無數患者得以康復,無數家庭重拾幸福。互聯網的發明,把全世界連為一體,過不了多久,石頭里也會嵌入芯片,在這個世界上有生命的、無生命的各種物質之間都可能進行通訊,人們的生活面貌已經徹底改變了。
當然,科學也是雙刃劍:原子彈爆炸了,核戰爭始終威脅著人類;在對基因組這套上帝給出生命密碼沒有全面理解以前,任何盲動都可能導致基因污染,以至于玩火自焚;互聯網上的虛擬生存讓人們感到更加孤獨。
怎樣做研究(二)
研究的層次
研究是分層次的,很多大科學家在晚年登上了最高層,比如錢學森在80年代倡導思維科學,他對整個科學技術體系進行了重新分類。在中國的大學里,分為一級學科,二級學科等,我就處在計算機科學技術一級學科下面的計算機應用技術二級學科下。二級學科的帶頭人稱為學科帶頭人,二級學科下面一個研究方向的帶頭人稱為學術帶頭人,我就被指定為學術帶頭人。
我的研究方向是信息檢索,信息檢索下面又有子方向,比如文本檢索、文本挖掘、跨語言檢索、跨媒體檢索等,子方向下面設立具體的科研課題,比如文本挖掘中的多文檔自動文摘課題,針對一項課題又有不同的解決辦法,基于事件抽取與集成的多文檔文摘就是利用一種具體的解決問題的方法。
總結來說,就是6個層級:
A. 一級學科
B. 二級學科
C. 研究方向
D. 子方向
E. 課題
F. 基于某種方法對課題進行的具體研究
君子思不出其位,我是學術帶頭人,因此主要在思考C類的問題,也就是和信息檢索相關的問題。一個學院的院長通常會思考A類的課題,學科帶頭人或者說是一個博士點的點長是要考慮B類問題的。一個人對相關的方向或學科有所了解,對自己的研究工作是很有好處的,只有看清了整體的學科面貌,才能知道自己處在那個位置上,自己未來的方向在哪里。我在讀博士以及在微軟做副研究員的時候,只看到E類問題,想到最多的是F類問題,因此你讓我提一個新方向,讓我對一項技術進行預測,我茫然無知。后來擔任院長助理,負責學院的成果轉化,需要了解學院里各個方向的發展狀態,使我的視野開闊了一些。盡管我凡事不求甚解,但是喜歡總結歸納,因此對信息檢索與其它學科的關系有了更多地認識,這對后來的選題很有幫助,特別是在應用研究方面,心里比較有底。
學科好比一棵大樹的樹根,研究方向如同樹干,具體的課題就是枝葉了。和學科中各個方向都相關的研究課題是最基礎的研究課題,比如在人工智能中,各類機器學習算法是圖像識別、語音識別和語言理解等各個方向都離不開的,機器學習技術提高一步,好比樹根抬高了一寸,各項應用技術也都跟著進步,因此越是基礎的研究,越會對業界產生較大較深遠的影響力。不過,基礎研究的突破比較難,而在某個應用課題上不考慮一般情況,只考慮具體需要,成功的可能性大。枝葉上的課題做多了,經過合并同類項,就會發現比較共性的基礎課題,比如我們在做問答系統、多文檔文摘、例句檢索等課題時發現復述(paraphrasing)是一個共性的問題,于是把復述單拿出來展開專門的研究,如此,可以越做越深。
學者的層次
研究有層次,學者也有層次,大致可以分為:
A. 大家(劍客):提出問題
B. 專家(俠客):解決問題
C. 學徒:修修補補
D. 抄襲者:抄來抄去
E. 搞偽科學的人:弄虛作假
A類是大家,站得高,看得遠,他們往往能夠前瞻性地提出某個學科領域中的若干重大問題,最著名的是希爾伯特的23個問題,對數學界影響深遠。提出問題其實也是解決問題的一種方式,只不過他們是在很高的層面解決問題,類似一個軟件系統分析員,他把一個復雜的工程問題分解為若干個有機聯系的子問題,然后宣布只要這幾個子問題解決了,整個大問題也就解決了。至于這幾個子問題到底怎樣解決,或者說相應的子系統到底怎樣開發,他就不管了。胡亂地提問題并不難,小孩子也會向大人提出各種各樣有趣的問題,有的大人也答不出來,問題的關鍵在于在適當的時候提出適合當前學術發展階段的關鍵性課題,這絕對不是一般人能夠做到的,這是需要具有對整個領域全面深入的理解才行的。
B類是專家,是在某個研究方向上有專長的人,他們沿著大家指出的方向探索前進,提出全新的方法體系來解決問題。比如在機器翻譯領域中,日本長尾真教授提出了基于實例的機器翻譯方法,從一個全新的視角看待機器翻譯問題。專家經驗豐富,能夠自由地駕馭課題,穩步地推動課題的進展。
C類是學徒,就是我們這些普通的研究人員了,這部分人的注意力在具體的課題上。學徒們還沒有宏大的視野,沒有捕捉全局戰略要點的本事,也還沒有在一個研究方向上提出原創性的解決之道,他們跟在拓荒者后面撿拾麥穗,他們負責對科學大廈修修補補。他們一會兒聽說了一個新的機器學習方法,趕緊在自己的課題上試一下;一會兒發現了一個以前忽略了的新的特征,立即想方設法把這個特征提取出來;一會兒為了參加一個技術評測,耐心地調一調系統參數;一會兒為了發表一篇論文構造出一個試驗來。我們每天的研究活動差不多都是在這樣進行的,很多時候在原地打轉轉。
我這樣描述學徒們的工作情景絲毫沒有貶低的意味,在達到專家的水平,證悟研究真諦以前,跌跌撞撞、渾渾沌沌是在所難免的。只要遵守誠信之道,不抄襲,不造假,點點滴滴的貢獻對科學界也是有幫助的。從更高的要求看,學徒的目標應該是成為專家,應該時常靜下心來想一想,自己的工作是否有價值,是否有新意,揣摩一下大家們、專家們到底是怎樣思考問題的,在不斷地反思與實踐中向上邁進。
D類學者根本算不上學者,他們為了評職稱等目的,對別人的論文進行抄襲拼湊,他們是思想的竊賊,對學術界毫無貢獻可言。
E類學者不僅僅是做賊了,他編造偽科學,毀壞科學界在公眾中的形象,他們是科學界的公敵。
以上的分類也只是為了討論的方便,在各類之間并沒有明確的界限,我只是依次談出我心中做學問的境界而已。
在人類已知的世界和未知的世界之間有一條動態邊界,科學家就站在這條邊界上,他們是挑戰未知世界的勇士,他們每向前邁出一步,就意味著整個人類的已知世界向前拓展了一步,由此足見科學工作的艱難和科學家的偉大。
研究又好比爬山,一座座山峰如同一個個研究領域,大家已登峰造極,一覽眾山小,把東南西北各條山路上的溝溝坎坎,把此山與他山之間的距離關系看得清清楚楚。隔行如隔山,隔行不隔道,在一個領域做到頂尖的學者已入化境,一通百通,你把另一個領域的問題講給他聽,他往往也能夠很快地抓到要害。專家已到半山腰,看不到山的全貌,但是他找到了一條通往山頂的道路,并一步一步地向上攀登著。學徒還沒有進入山門,他們一會兒仰望山頂,一會兒看看山腰,在山腳下繞來繞去找不到門徑,費力不少,卻并沒有縮短與山頂的距離。
怎樣做研究(三)
怎樣選題
前文曾提到科學研究的層次,并分了6個層級。此處所說的選題指的是從C到E三個層次上的選擇問題,即:C. 研究方向、D. 子方向、E. 課題。選擇研究方向是實驗室(Lab)主任們需要重點思考的事情,選擇子方向是研究小組(Group)的組長們需要重點思考的事情,選擇課題是研究生們需要重點思考的事情。
選擇太多,很容易讓人困惑,要想理出一個頭緒來,需要一些基本的原則。微軟的許峰雄來訪時談到了他選擇課題的三個標準:有足夠的興趣,能成為世界第一,能賺錢。(!)興趣,這個原則是非常重要的,我贊同,獲得國家最高科技獎的"黃土之父"劉東生院士是搞地球環境科學的,經常在野外作業,按常人推斷,這該是多么枯燥艱苦的工作啊,但他說:"枯燥?不!因為經常有新發現,其中的樂趣難以形容"。我堅信任何一個成功的科學家的直接工作動源都是興趣,而不是意志。(2)成為世界第一,不容易,但是應該作為一種判斷標準,如果某個領域已經非常成熟,很難有什么創新了,或者大牛云集,已經打破頭了,則應該有所回避。(3)賺錢,許峰雄是在工業研究院中工作,比較注重實用,因此他強調了"賺錢",我是在工科大學里工作,也比較偏重應用,因此是贊同"能賺錢"這個標準的。不過,"能賺錢"不等于立即賺錢,5年、10年,20年后能夠賺錢的研究課題都是值得關注的。
談談我選擇課題的一些體會:
1、 要有實際需求
一個課題必須有實際需求,可能是現實的需求,也可能是潛在的需求;可能是直接的需求,也可能是間接的需求,總之是的的確確被人們所需要的。據個反例,比如自動文摘,自動文摘是我的博士論文課題,但是實際應用需求始終不清楚,自動文摘的結果用于編輯出版,質量肯定無法保證,用于幫助人們快速瀏覽資料吧, Google提供的包含查詢詞的簡單的Snippet就起到了這個作用,因此,至今基于全文分析的單文檔自動文摘到底用到哪里,仍然不清楚,這方面的研究已經有50多年的歷史了,仍然是不死不活,總是找不到應用就無法得到政府和企業界的持續性支持,以往的付出成為雞肋。我覺得單自動文摘不是一個好課題,目前階段多文檔文摘,或者說對某個題目的自動綜述分析是非常好的題目。
2、 有較大的未知空間
以手寫體漢字識別為例,市場上已經大面積應用了,在研究上就不宜再展開。
3、 與自己以往的工作有關聯
如果你覺得自己的研究領域太窄,或者競爭對手太多,或者自己缺乏興趣,則可以適當擴展研究方向,但最好是相關性地擴展,比如從自然語言處理(NLP)擴展到信息檢索(IR),IR要用到NLP的技術,這種擴展是從底層技術到應用系統的擴展,很自然。再比如從圖片檢索擴展到視頻檢索,只是處理對象有變化,很多原有的技術優勢仍然能夠發揮。如果跳躍性太大,比如搞NLP,忽然發現做數據挖掘有前途,于是單純地轉向數據庫中數據挖掘,和文本處理完全脫節,這種做法一方面無法發揮既有的技術積累,另一方面也讓同行感覺你不夠專注,不容易得到認可。最要命的是有的人根本就沒有自己的方向,什么課題都敢接,這樣的人可以一時間讓人覺得風風火火,經費也很充足,但過不了多久就會摔落下去,因為缺乏積累,學術形象不清,公雞下蛋,干了自己不擅長的事情,在學術圈還怎么混?
4、 有可能得到國家的支持
對于資深學者,他選定一個課題后,可以寫出立項建議,去說服政府或軍方支持他的工作,從而填補國家空白,成為國內這個方向的先驅。哈工大的楊孝宗老師借鑒 CMU在wearable computing方面的研究成果,在國內率先提出穿戴計算機的概念,堅持多年,就獲得了軍方的認可。對于剛出道的年輕人,無力直接影響政府,那只有自己預先判定一個幾年后可能成為熱點的方向,先走一步,做出一些成績來,等到大氣候適宜的時候,由于他已經取得了一定的成果,也有可能被認可為這個領域的先行者,得到國家的支持。
課題的類型
對一個課題的類型要有一個判斷,是研究型的還是開發型的,如果是研究型的,要組織博士生們來攻關,鼓勵大家大膽嘗試,提出創見;如果是開發型的,要更多地召集碩士生們來做,強調利用一切現有的技術手段把技術或系統做到實用可靠。這兩者要分的比較清楚,既不能通過各種打補丁的方法,或者說一大堆小技巧來對付研究型的課題,因為那樣是做不出突破性進展的,也不能在開發類課題上總是異想天開,嘗試還很不成熟的技術。
如果是研究型課題,還要區別是基礎研究還是應用研究,基礎研究的結果不能直接被用戶使用,類似重工業,應用研究的結果最終用戶直接就能夠用上,類似輕工業。對于基礎研究,可以拋開具體應用的約束,專注于一些科學原理技術原理的突破。對于應用研究,則需要考慮用戶的需求。
課題還有長期(long term)和短期(short term)之分,長期研究的課題往往難度大,研究結果難以預料,短期項目則比較好預測,可以速戰速決。
怎樣做研究(四)
在一個具體的題目上作研究,應該遵從怎樣的程序呢?我覺得可以概括為"螺旋式深入",也就是在"閱讀","思考","實驗","寫作",再閱讀。。。這四個階段的時間分配可以根據實際情況靈活調整,剛進入課題的研究生閱讀調研花費的時間要多一些,而在一個課題上已經開展了一兩年工作的人則可能增量式地閱讀資料,閱讀時間自然比起步時少一些。專門用于思考、設計、推演的時間可能并不多,但思考是滲透在其它三個階段中不斷進行的,因此總的思考時間并不少。實驗中編程的時間應該盡可能短,用更多的時間進行實驗數據的分析。寫作是常常被中國的研究生忽略的環節,寫作的時間要足夠長。收集資料,了解別人的工作,找出問題所在,針對性地提出自己的創意,用實驗驗證自己創意的正確性,總結歸納,撰寫論文,發現新的問題,再收集資料,如此反復,這是研究活動的大致流程。
怎樣閱讀資料
收集資料、閱讀資料是從事研究工作的第一步,但是如何收集、閱讀資料卻很有學問,初學者如果沒有得到足夠的指導,常常走很多彎路。
1、 閱讀重要的論文
目前互聯網上的信息量太大了,對每一條信息的重要性、可靠性的判斷是一個人采集信息的關鍵環節。如果判斷一篇論文是否重要呢?GoogleScholar給出的引用數是一個有效指標,很多學者都引用的文章往往就是有價值的論文。有的同學覺得看中文論文容易,于是把自己能夠查到的中文論文一網打盡,反復閱讀,但是很多發表在三流刊物上為了評職晉級而炮制的論文完全沒有閱讀的價值,白白耽誤了時間。即使是英文論文,國外一樣有濫竽充數的文章,這樣的論文引用數肯定低,用引用數可能很容易地把這樣的論文淘汰掉。
計算機領域的頂級會議論文非常重要,在NLP領域有ACL,在IR領域有SIGIR,在機器翻譯領域有MT Summit,這些頂級會議的論文質量很高,內容很新,應該高度關注。期刊上的論文是一個作者或機構一個階段的研究成果的總結,通常質量較高,但由于審稿及編輯出版的周期很長,因此內容不夠新,適當關注即可。NLP領域的CL,機器翻譯中的MT,信息檢索領域的IP&M和JASIST等都是很好的期刊。進入一個領域,必須立即了解該領域有哪些頂級的國際會議和國際期刊。
2、以作者為線索理清脈絡
閱讀論文一定要注意論文的作者是誰,研究機構是哪里,以作者為線索理一理就會發現全世界搞你這個方向的也就那么幾個、十幾個研究機構、研究者,以后就跟蹤這些人的研究工作即可,還能夠發現該作者的研究工作的演進脈絡。如果拿到一篇文章就讀,讀完了也不知道作者是誰,時間長了,就會感到暈頭暈腦,不知道從哪個期刊或會議上就會冒出一篇相關文章來,讓你防不勝防。
3、 閱讀最新的論文
學術發展很快,要集中盡力閱讀近5年,特別是近3年的論文,對于5年前的論文,只看引用率最高的經典文章即可。
4、 抓住論文的要害
讀完一篇論文必須了解哪些關鍵內容呢?我覺得應該包括以下方面:作者為什么要做這項工作?要解決的是一個什么問題?作者在解決問題時遇到了怎樣的困難?為了解決他的困難他提出了什么樣的解決辦法?試驗結果是否可能真的證明他的方法好,數據是否充分,有沒有和別人的工作,別的方法進行對比?你認為他的方法是否新穎,你從中學到了什么?該方法有哪些不足,你是否立即有了新的改進方案?如果有立即記錄下來。帶著上述問題,抓住要點,做好記錄,一篇長文就會像庖丁解牛一樣轟然倒下。
5、 批判式閱讀
真理越辯越明,我們讀的是一篇學術論文,不是《圣經》,不能帶著崇敬的心理去閱讀,要像一個審稿人那樣帶著批判挑剔的心理閱讀論文,在閱讀中不斷地找出論文中的問題,選題上的,方法上的,實驗上的,表述上的,并不斷地通過積極獨立的思考給出自己認為見解。只有這樣,資料才能夠為你所用,而不會成為你的包袱。有的同學讀資料,越讀越喪失信心,發現別人做得太好了,自己的想法都被別人做完了,資料全讀完了,自己也準備換課題了,這是失敗的讀法。
中國的研究生要有信心,不要被國外所謂的名家嚇住。中國的科研水平在快速提高,科研人員的素質也在快速提高。一位美籍華裔企業家在一篇文章中寫道:"可不幸的是,除了很少頂尖學校的博士外,大部分博士所做的研究課題都是陳舊或者沒有意義的。"不知道頂尖高校的含義是什么,但是我覺得我們的研究生要對自己的國家有信心,對自己的學校有信心,對自己的倒是有信心,對自己有信心。只要我們掌握正確的研究方法,廣泛閱讀國外最新的研究成果,大膽嘗試自己人為正確的方法,充分釋放我們的聰明才智,我們就絲毫不用對國外的研究工作頂禮膜拜。在科學研究上,歐美人從內心里是瞧不起我們亞洲人,我們中國人的,以至于歐美歸來的學者們也以歐美為樣板來評估我們教育科研體制,只要和美國不一樣就是大錯特錯了,中國高校的教師們都是在誤人子弟。我奉勸每一位研究生建立不崇拜權威,不崇拜歐美,只服從真理的獨立思維模式,大膽質疑大膽批判,只有這樣才能不死于他人之言下,才能有活脫脫的自己。
posted @
2012-04-13 19:08 Seraphi 閱讀(336) |
評論 (0) |
編輯 收藏