終端搜索工具

作人嘛,開心就行了

爲了不遺忘,先附上repo連接,有興趣的拿去用咯。python

https://github.com/guoruibiao/worktools/tree/master/searchergit

前言

平時都是在終端下進行開發,文件少代碼量不大的時候,查找某些方法也好,關鍵字也罷,都還能夠,不算費時。可是隨着代碼量的不斷增長,項目越寫越大,不少文件,方法就根本找不到到底在哪一個地方了。這個時候再去一個一個的找的話,就很差玩了。github

也許你會說,我有IDE,全局搜索下不就行了,幹嗎這麼費事咧。是的,IDE有其獨特的優勢。可是徹底在終端下工做,就用不了純粹的IDE了。VIM中有一個插件,叫ctrlp。在normal模式下按下Ctrl+P鍵,就能夠查找本級目錄(以及子目錄)下包含有輸入的關鍵字的文件了。以下圖。 redis

VIM插件Ctrlp的文件查詢效果

相信你也能看出來了,ctrlp能找到的只是一個文件名,對於內部的變量仍是愛莫能助的。固然了,在VIM中其實也不是個事。各類插件工具,搞一搞,不輸IDE。可是這和今天要寫的工具的預期有點差距。咱們要找到某個目錄下包含某個方法,某個關鍵字的具體的位置。sql

在正式開始製做工具以前,下面須要先熟悉一下一些基礎的東西。shell

查找

查找,基本上分爲兩塊。一個是查找文件,一個是查找內容。json

文件查找

最經常使用的文件查找命令是find。vim

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還會幫咱們進行遞歸式的查找。api

內容查找

實現內容查找的方式有不少方式,使用grep命令,或者使用Perl,Python,shell等腳本語言來作處理都是能夠的。固然,不一樣的方式實現的最終效果也會有差距。bash

若是隻是簡單的想知道哪一個文件包含了目標關鍵字,使用grep就能夠了。

➜  worktools git:(master) ✗ grep 遞歸 searcher/searcher.py 
        # 明天作下遞歸版本
➜  worktools git:(master) ✗ 
複製代碼

可是若是想知道包含了關鍵字在(多個)文件中的行數,位置,這個時候在使用grep等命令就有點捉襟見肘了。但也不是說不能實現,如:

➜  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) ✗ 

複製代碼

而使用一些稍微高級一點的腳本語言,能實現的功能就會更多樣化。好比高亮顯示查找的關鍵字,添加行號元數據等等,這些使用高級語言,會更方便一點。

高亮工具

大二的時候接觸的Python,一開始也是在命令行裏面不斷摸索這,從理解命令行參數的使用到本身封裝了一個getpass2的庫。什麼進度條啊的都算是玩了下。在這麼多的庫中,有一個讓我確實印象深入。那就是colorama。一個可讓非黑即白的終端瞬間變得多姿多彩起來。

對我而言,colorama足夠好用,可是init(autoreset=True)有時候並不能知足個人需求。好比我只想高亮某個關鍵字,須要操做的那就太多了。因而我打算本身寫一個相似的,知足個人需求就行了,因而有了colorcmd。在正式寫代碼以前,仍是要先理解下如何讓終端輸出多種顏色。

知識點普及

在支持真彩色的終端中,有這麼一個約定。

ESC鍵的轉移序列爲ASCII碼的\033. 變換顏色的格式以下:

\033[顯示方式;前景色;背景色m
複製代碼

須要注意的是:顯示方式,前景色,背景色至少存在一個就能夠。若是存在多個,記得使用英文的分號進行分割。

顯示方式有以下取值:

  • 0 關閉全部效果
  • 1 高亮
  • 4 下劃線
  • 5 閃爍
  • 7 反色
  • 8 不可見

顯示方式特效

前景色以3開頭,背景色以4開頭。緊鄰的爲顏色取值,分別爲:

  • 0 黑色
  • 1 紅色
  • 2 綠色
  • 3 黃色
  • 4 藍色
  • 5 紫色
  • 6 青色
  • 7 白色

簡單的來測試下。

字體顏色特徵

工具編寫

這裏我打算使用shell配合Python實現一個關鍵字高亮搜索的小工具。具體會有以下文件:

colorcmd.py 終端顏色樣式工具類
searcher.py 關鍵字搜索
searcher.sh 文件搜索
複製代碼

searcher.sh

#!/usr/bin bash
# 使用shell配合Python腳本查找文件中某一個變量或者字符串所在的行數


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()
        # 遍歷每一行,讀取包含關鍵字的行,並進行臨時存儲,用於後續美化輸出
    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")
""" # 以前用過一個colorama的庫,挺好用的,可是有一個缺點就是有時候init(autoreset=True)並不很好使,究其緣由,仍是設計層面的問題 因而我打算使用「包裝」的思想,來作一個更好用一點的出來。 """

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"
    """ 顏色相關工具類 """
    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"
    """ 樣式相關,前景色,背景色,加粗,下劃線等 """
    def __init(self):
        pass

class Enhancer(object):
    """ 曾經有一個tag的交叉疊加,給了我這個思路。目標是作成一個無限疊加的加強品。 """
    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)


複製代碼

代碼比較簡單,可是仍是有很大的拓展空間的。

  • 好比以多線程的形式進行查找,這樣速度會更加迅速。

  • 終端輸出的美化效果,如今就是個簡單的輸出了,若是有必要的話,能夠藉助PrettyTable這個庫實現更優雅的輸出效果。

如何使用

這個工具的入口是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,那麼應該是~/.bashrc. 沒有的話就新建一個。)
# 在最後面加上這麼一行命令。
alias search='sh /absolute path/searcher.sh'
# 保存退出後還差一句命令,讓別名的配置能夠在當前的會話終端內生效。
source ~/.zshrc
複製代碼

完成後就能夠很方便的在終端內搜索了。 格式以下:

search path keyword
複製代碼

作人嘛,開心就行了
相關文章
相關標籤/搜索