為了避免遺忘,先附上repo鏈接骡楼,有興趣的拿去用咯熔号。
https://github.com/guoruibiao/worktools/tree/master/searcher
前言
平時(shí)都是在終端下進(jìn)行開(kāi)發(fā),文件少代碼量不大的時(shí)候鸟整,查找某些方法也好引镊,關(guān)鍵字也罷,都還可以篮条,不算費(fèi)時(shí)弟头。但是隨著代碼量的不斷增加,項(xiàng)目越寫越大涉茧,很多文件赴恨,方法就根本找不到到底在哪個(gè)地方了。這個(gè)時(shí)候再去一個(gè)一個(gè)的找的話降瞳,就不好玩了嘱支。
也許你會(huì)說(shuō),我有IDE挣饥,全局搜索下不就好了除师,干嘛這么費(fèi)事咧。是的扔枫,IDE有其獨(dú)特的優(yōu)點(diǎn)汛聚。但是完全在終端下工作,就用不了純粹的IDE了短荐。VIM中有一個(gè)插件倚舀,叫ctrlp。在normal模式下按下Ctrl+P鍵忍宋,就可以查找本級(jí)目錄(以及子目錄)下包含有輸入的關(guān)鍵字的文件了痕貌。如下圖。
相信你也能看出來(lái)了糠排,ctrlp能找到的只是一個(gè)文件名舵稠,對(duì)于內(nèi)部的變量還是心有余而力不足的。當(dāng)然了,在VIM中其實(shí)也不是個(gè)事哺徊。各種插件工具室琢,搞一搞,不輸IDE落追。但是這和今天要寫的工具的預(yù)期有點(diǎn)差距盈滴。我們要找到某個(gè)目錄下包含某個(gè)方法,某個(gè)關(guān)鍵字的具體的位置轿钠。
在正式開(kāi)始制作工具之前巢钓,下面需要先熟悉一下一些基礎(chǔ)的東西。
查找
查找谣膳,基本上分為兩塊竿报。一個(gè)是查找文件,一個(gè)是查找內(nèi)容继谚。
文件查找
最常用的文件查找命令是find烈菌。
find path -name "regex "
# 示例
? worktools git:(master) ? find ./ -name "*.p*"
.//searcher/colorcmd.pyc
.//searcher/searcher.py
.//searcher/colorcmd.py
.//sqlhelper/sqlhelper.py
.//sqlhelper/datatransfer.py
.//dingding/dingding.py
.//interfacetool.py
.//getrealip.py
.//detect-actions.py
.//getall/finder.py
.//getall/get.py
.//redis-analyzer/server.py
.//redis-analyzer/redishelper.py
.//redis-analyzer/__init__.py
.//redis-analyzer/__pycache__/redishelper.cpython-36.pyc
.//redis-analyzer/temp.py
可以看出find還會(huì)幫我們進(jìn)行遞歸式的查找。
內(nèi)容查找
實(shí)現(xiàn)內(nèi)容查找的方式有很多方式花履,使用grep命令芽世,或者使用Perl,Python诡壁,shell等腳本語(yǔ)言來(lái)做處理都是可以的济瓢。當(dāng)然,不同的方式實(shí)現(xiàn)的最終效果也會(huì)有差距妹卿。
如果只是簡(jiǎn)單的想知道哪個(gè)文件包含了目標(biāo)關(guān)鍵字旺矾,使用grep就可以了。
? worktools git:(master) ? grep 遞歸 searcher/searcher.py
# 明天做下遞歸版本
? worktools git:(master) ?
但是如果想知道包含了關(guān)鍵字在(多個(gè))文件中的行數(shù)夺克,位置箕宙,這個(gè)時(shí)候在使用grep等命令就有點(diǎn)捉襟見(jiàn)肘了。但也不是說(shuō)不能實(shí)現(xiàn)铺纽,如:
? worktools git:(master) ? find ./ -name "*.p*" | xargs grep 遞歸
.//searcher/searcher.py: # 明天做下遞歸版本
? worktools git:(master) ? find ./ -name "*.p*" | xargs grep hello
.//interfacetool.py:#cmd = "wget http://fanyi.badu.com/v2transapi?query=hello | python -m json.tool"
? worktools git:(master) ? find ./ -name "*.p*" | xargs grep coding
Binary file .//searcher/colorcmd.pyc matches
.//searcher/searcher.py:#coding: utf8
.//searcher/searcher.py:sys.setdefaultencoding("utf8")
.//searcher/colorcmd.py:# coding: utf8
.//searcher/colorcmd.py:sys.setdefaultencoding("utf8")
.//sqlhelper/sqlhelper.py:# coding: utf8
.//sqlhelper/datatransfer.py:# coding: utf8
.//sqlhelper/datatransfer.py:sys.setdefaultencoding('utf8')
.//dingding/dingding.py:# coding: utf8
.//interfacetool.py:# coding: utf8
.//getrealip.py:# coding: utf8
.//detect-actions.py:# coding: utf8
.//getall/finder.py:# coding: utf8
.//getall/get.py:# coding: utf8
.//redis-analyzer/server.py:# coding: utf8
.//redis-analyzer/server.py:sys.setdefaultencoding('utf8')
.//redis-analyzer/redishelper.py:# coding: utf8
.//redis-analyzer/__init__.py:# coding: utf8
.//redis-analyzer/temp.py:# coding: utf8
? worktools git:(master) ?
而使用一些稍微高級(jí)一點(diǎn)的腳本語(yǔ)言柬帕,能實(shí)現(xiàn)的功能就會(huì)更多樣化。比如高亮顯示查找的關(guān)鍵字狡门,添加行號(hào)元數(shù)據(jù)等等陷寝,這些使用高級(jí)語(yǔ)言,會(huì)更方便一點(diǎn)其馏。
高亮工具
大二的時(shí)候接觸的Python凤跑,一開(kāi)始也是在命令行里面不斷摸索這,從理解命令行參數(shù)的使用到自己封裝了一個(gè)getpass2的庫(kù)叛复。什么進(jìn)度條啊的都算是玩了下饶火。在這么多的庫(kù)中鹏控,有一個(gè)讓我確實(shí)印象深刻。那就是colorama肤寝。一個(gè)可以讓非黑即白的終端瞬間變得多姿多彩起來(lái)。
對(duì)我而言抖僵,colorama足夠好用鲤看,但是init(autoreset=True)有時(shí)候并不能滿足我的需求。比如我只想高亮某個(gè)關(guān)鍵字耍群,需要操作的那就太多了义桂。于是我打算自己寫一個(gè)類似的,滿足我的需求就好了蹈垢,于是有了colorcmd慷吊。在正式寫代碼之前,還是要先理解下如何讓終端輸出多種顏色曹抬。
知識(shí)點(diǎn)普及
在支持真彩色的終端中溉瓶,有這么一個(gè)約定。
ESC鍵的轉(zhuǎn)移序列為ASCII碼的\033.
變換顏色的格式如下:
\033[顯示方式;前景色;背景色m
需要注意的是:顯示方式谤民,前景色堰酿,背景色至少存在一個(gè)就可以。如果存在多個(gè)张足,記得使用英文的分號(hào)進(jìn)行分割触创。
顯示方式有如下取值:
- 0 關(guān)閉所有效果
- 1 高亮
- 4 下劃線
- 5 閃爍
- 7 反色
- 8 不可見(jiàn)
前景色以3開(kāi)頭,背景色以4開(kāi)頭为牍。緊鄰的為顏色取值哼绑,分別為:
- 0 黑色
- 1 紅色
- 2 綠色
- 3 黃色
- 4 藍(lán)色
- 5 紫色
- 6 青色
- 7 白色
簡(jiǎn)單的來(lái)測(cè)試下。
工具編寫
這里我打算使用shell配合Python實(shí)現(xiàn)一個(gè)關(guān)鍵字高亮搜索的小工具碉咆。具體會(huì)有如下文件:
colorcmd.py 終端顏色樣式工具類
searcher.py 關(guān)鍵字搜索
searcher.sh 文件搜索
searcher.sh
#!/usr/bin bash
# 使用shell配合Python腳本查找文件中某一個(gè)變量或者字符串所在的行數(shù)
filelist=`find $1 -name "*.*"`
for file in ${filelist[@]};do
#echo $file;
python /Users/changba164/guo/tools/worktools-master/worktools/searcher/searcher.py $file $2
done;
#find $1 -name "*.*" | xargs python $2
searcher.py
#!/usr/bin python
#coding: utf8
import sys
reload(sys)
sys.setdefaultencoding("utf8")
import re
import os
from colorcmd import Color, Style, Enhancer
def find(filepath, keyword):
if os.path.isdir(filepath):
# 明天做下遞歸版本
return []
result = []
with open(filepath, 'r') as file:
lines = file.readlines()
file.close()
# 遍歷每一行抖韩,讀取包含關(guān)鍵字的行,并進(jìn)行臨時(shí)存儲(chǔ)吟逝,用于后續(xù)美化輸出
counter = 0
for line in lines:
counter += 1
if keyword.lower() in line.lower():
wrappedword = Enhancer.mix(keyword, Color.BLACK_DEEPGREEN, Style.HIGHLIGHT+Style.UNDERLINE+Style.BLINK)
tmp = {"number": counter, "line":line.rstrip("\n").replace(keyword, wrappedword)}
result.append(tmp)
return result
def pretty_print(filepath, rows):
for row in rows:
if row is not None or row != []:
print "-------"*5 + filepath + "-------"*5
print "Line: {}\t {}".format(row['number'], row['line'])
filepath = sys.argv[1]
keyword = sys.argv[2]
rows = find(filepath, keyword)
pretty_print(filepath, rows)
colorcmd.py
#!/usr/bin python
# coding: utf8
import sys
reload(sys)
sys.setdefaultencoding("utf8")
"""
# 之前用過(guò)一個(gè)colorama的庫(kù)帽蝶,挺好用的,但是有一個(gè)缺點(diǎn)就是有時(shí)候init(autoreset=True)并不很好使块攒,究其原因励稳,還是設(shè)計(jì)層面的問(wèn)題
于是我打算使用“包裝”的思想,來(lái)做一個(gè)更好用一點(diǎn)的出來(lái)囱井。
"""
class Color(object):
CLEAR = "\33[0m"
# 字體顏色 前景色
FORE_BLACK = "\33[30m"
FORE_RED = "\33[31m"
FORE_GREEN = "\33[32m"
FORE_YELLOW = "\33[33m"
FORE_BLUE = "\33[34m"
FORE_PURPLE = "\33[35m"
FORE_DEEPGREEN = "\33[36m"
FORE_WHITE = "\33[37m"
# 背景色
BACK_BLACK = "\33[40"
BACK_RED = BACK_DEEPRED = "\33[41m"
BACK_GREEN = "\33[42m"
BACK_YELLOW = "\33[43m"
BACK_BLUE = "\33[44m"
BACK_PURPLE = "\33[45m"
BACK_DEEPGREEN = "\33[46m"
BACK_WHITE = "\33[47m"
# 黑底彩色
BLACK_BLACK = "\33[90m"
BLACK_RED = BLACK_DEEPRED = "\33[91m"
BLACK_GREEN = "\33[92m"
BLACK_YELLOW = "\33[93m"
BLACK_BLUE = "\33[94m"
BLACK_PURPLE = "\33[95m"
BLACK_DEEPGREEN = "\33[96m"
BLACK_WHITE = "\33[97m"
"""
顏色相關(guān)工具類
"""
def __init__(self):
pass
class Style(object):
CLEAR = "\33[0m"
HIGHLIGHT = "\33[1m"
UNDERLINE = "\33[4m"
BLINK = "\33[5m"
REVERSE = "\33[7m"
BLANKING = "\33[8m"
"""
樣式相關(guān)驹尼,前景色,背景色,加粗庞呕,下劃線等
"""
def __init(self):
pass
class Enhancer(object):
"""
曾經(jīng)有一個(gè)tag的交叉疊加新翎,給了我這個(gè)思路程帕。目標(biāo)是做成一個(gè)無(wú)限疊加的增強(qiáng)品。
"""
def __init__(self):
pass
@staticmethod
def highlight(text="", color=Color.FORE_RED, style=Style.CLEAR):
return Style.HIGHLIGHT + style + color + text + Style.CLEAR
@staticmethod
def mix(text, color=Color.CLEAR, style=Style.CLEAR, highlight=False):
return style + color + text + Style.CLEAR
if __name__ == "__main__":
#print "\33[5m"+Color.FORE_GREEN+"Hello World!"+"\33[0m"
text = "郭璞"
print Enhancer.highlight(text, Color.BACK_GREEN, Style.BLINK)
print Enhancer.mix("what a amazing colorama!", Color.BLACK_PURPLE, Style.UNDERLINE+Style.HIGHLIGHT+Style.BLINK)
代碼比較簡(jiǎn)單地啰,但是還是有很大的拓展空間的愁拭。
比如以多線程的形式進(jìn)行查找,這樣速度會(huì)更加迅速亏吝。
終端輸出的美化效果岭埠,現(xiàn)在就是個(gè)簡(jiǎn)單的輸出了,如果有必要的話蔚鸥,可以借助PrettyTable這個(gè)庫(kù)實(shí)現(xiàn)更優(yōu)雅的輸出效果惜论。
如何使用
這個(gè)工具的入口是searcher.sh
,所以正常使用的話可以這么干:
sh ./searcher.sh targetpath keyword
# 示例
? searcher git:(master) ? sh searcher.sh ./ default
---------.//searcher.py------------
Line: 5 sys.setdefaultencoding("utf8")
---------.//colorcmd.py------------
Line: 5 sys.setdefaultencoding("utf8")
? searcher git:(master) ?
但是這樣每次都要輸入一下sh命令 挺麻煩的。因此止喷,放到alias里面就好多了馆类。
vim ~/.zshrc (我的Mac安裝了zsh,所以這里是~/.zshrc, 如果你用的是Linux弹谁,那么應(yīng)該是~/.bashrc. 沒(méi)有的話就新建一個(gè)乾巧。)
# 在最后面加上這么一行命令。
alias search='sh /absolute path/searcher.sh'
# 保存退出后還差一句命令,讓別名的配置可以在當(dāng)前的會(huì)話終端內(nèi)生效僵闯。
source ~/.zshrc
完成后就可以很方便的在終端內(nèi)搜索了卧抗。
格式如下:
search path keyword