趣味集算:兩行搞定GREP搜索
What??jī)尚写a搞定GREP搜索?如果不是經(jīng)常使用Linux,估計(jì)你看到這個(gè)標(biāo)題后會(huì)一臉不屑加滿臉狐疑: GREP搜索是個(gè)什么鬼?又一個(gè)搜索引擎問(wèn)世?比百度牛x嗎?樓主你過(guò)來(lái)講講,你是如何只用兩行代碼就搞定搜索的。我給你一個(gè)關(guān)鍵字,你能還我一堆URL?
誤會(huì)誤會(huì),你就是給我十個(gè)關(guān)鍵字,我也還不了一個(gè)URL的。因?yàn)槲艺f(shuō)的搜索,不是網(wǎng)絡(luò)搜索引擎。正如前面提到的,Linux,我說(shuō)的是Linux下的一個(gè)搜索命令,一個(gè)叫GREP的命令。 GREP(global search regular expression(RE) and print out the line),它是一種文本搜索工具,它能使用正則表達(dá)式搜索文本,并把匹配的行打印出來(lái)。比如我們想搜索一個(gè)名為readme.txt的文件中,有哪些行包含了raqsoft。則在Linux的命令行中只要輸入如下命令:
執(zhí)行后,控制臺(tái)就會(huì)打印出行號(hào),以及包含raqsoft字符串的那些行。
此刻,我想你不禁會(huì)問(wèn),兩行代碼就能搞定這么復(fù)雜的動(dòng)作?你不要騙我,俺讀書少,可也是寫過(guò)程序的人,就拿Java來(lái)說(shuō),光引用包、類名就得好幾行,然后你的變量總要有吧,你總得查找文件,寫個(gè)循環(huán)來(lái)搜索比對(duì)內(nèi)容吧。問(wèn)完后就一臉不屑地等著樓主如何自圓其說(shuō),樓主要如何不寫變量,不寫循環(huán),來(lái)完成示例中的搜索。因?yàn)椋藭r(shí)的你,腦子里面涌現(xiàn)出了下述畫面:
- import xxx;
- import …
- public class xx{
- String filePath,search;
- ArrayList<File> files = 列出filePath的文本文件
- for(File f:files){
- 讀取文件f的內(nèi)容
- for(String row:文件內(nèi)容){
- 如果包含search,打印行號(hào)和文件內(nèi)容
- }
- }
- }
是的,用常規(guī)編程語(yǔ)言來(lái)實(shí)現(xiàn)文本搜索,少不了變量,離不開循環(huán),不管是用C還是其他語(yǔ)言,浮現(xiàn)的偽代碼都跟上面類似,無(wú)非是幾個(gè)關(guān)鍵字的寫法不一樣??雌饋?lái),只寫兩行代碼完成上述功能,是癡人說(shuō)夢(mèng)。除非用的是人類語(yǔ)言:“給我打印所有文件中包含search的行出來(lái)!”嗯,想象力很豐富,人工智能嘛,呵呵。
看來(lái)是不信?上代碼!
A | |
1 | =directory@ps(path+”/*.txt”) |
2 | =A1.run(file(~).read@n().run(if(pos(~,string(search)),output([A1.~,” 第”+string(#)+”行:”,~].string())))) |
嘖嘖,真地只有兩行,果然沒有變量,也沒有循環(huán)!不過(guò)看起來(lái)怪怪的,居然每行前面還有個(gè)奇怪的等號(hào),但又沒有被賦值的對(duì)象。長(zhǎng)得這么奇怪的程序,它真能干活嗎?你可能還在懷疑,我寫的會(huì)不會(huì)是一段假代碼。不過(guò)沒關(guān)系,初次見面,有陌生感是正常的。
在DOS窗口讓它跑一遍,再貼個(gè)圖:
看到上述截圖,說(shuō)明這個(gè)代碼確實(shí)干活了。它不但能找到文本文件里的串,而且找得還很仔細(xì),它將給定目錄d:/config下的包含子目錄的所有文件都找了出來(lái)!
那么問(wèn)題來(lái)了,這門語(yǔ)言是如何處理變量的?比如上述代碼里沒有定義的A1是從哪來(lái)的?A1又是個(gè)什么類型的變量?不用定義就直接引用?那個(gè)賦值的等號(hào),但又沒有賦值對(duì)象是啥意思?還有確實(shí)沒看到for循環(huán)就遍歷了所有文件,是如何實(shí)現(xiàn)的?為了說(shuō)明這些問(wèn)題,還是得有圖,有圖有真相:
看到圖片,神秘語(yǔ)言也就露出了真容,原來(lái)是個(gè)叫做集算器的東東。同時(shí),也似乎好理解一些上述代碼了,原來(lái)上述語(yǔ)句都是寫在Excel里的??!且慢,看好了,這個(gè)不是Excel,是集!算!器!人家只是長(zhǎng)得跟Excel有點(diǎn)像好嗎。不過(guò)對(duì)于A1是從哪里來(lái)的有了解答,原來(lái)每個(gè)格子的名字就是變量。所以,不用定義變量就可以寫程序了。好吧,那么上述代碼為啥沒有循環(huán)呢?看不到循環(huán),并不代表它沒有,你肯定循環(huán)了是不是?對(duì)對(duì)對(duì),循環(huán)還是要的,至于到底是如何循環(huán)的,依然看圖:
上圖是一個(gè)數(shù)據(jù)內(nèi)容查看面板,就像調(diào)試程序時(shí)的watch窗口。左上角的A1表示當(dāng)前查看的是A1。那成員是什么意思?哦,原來(lái)A1就是一個(gè)封裝了數(shù)組的對(duì)象!此時(shí)的你有了一個(gè)大致的認(rèn)識(shí)。那么第二行代碼中A1.run()在你心中已經(jīng)有了答案,就是針對(duì)這個(gè)數(shù)組做一個(gè)循環(huán)嘛!原來(lái)如此!然后后面的代碼意思應(yīng)該就是讀取文件內(nèi)容,然后比較并輸出到控制臺(tái)。還有那個(gè)沒賦值對(duì)象的等號(hào)呢?這里的等號(hào)不是賦值的意思,而是表示后面跟上的是需要計(jì)算的表達(dá)式,沒有等號(hào)時(shí)就是一些其他的,比如常量、注釋、或者關(guān)鍵字等。
至此,只需兩行代碼就搞定GREP搜索,并不是噱頭,是真實(shí)可行的,且有實(shí)際功能的一個(gè)小工具。不過(guò),這文章還是有點(diǎn)標(biāo)題黨,兩行代碼的GREP并沒有做正則表達(dá)式匹配,也還不能支持大文件。那么,怎么才能實(shí)現(xiàn)完整的GREP呢?又需要多少行代碼呢?而且,我估計(jì)你心中仍有諸多疑惑,這種網(wǎng)格式語(yǔ)言到底有什么用?那種像是封裝了數(shù)組的對(duì)象又有什么好處?帶著你的好奇,繼續(xù)關(guān)注潤(rùn)乾軟件吧。