之前介紹過很多linux下查詢相關的命令,例如《linux中的檔案查詢技巧》,《find命令高階用法》,《如何檢視linux中檔案開啟情況-lsof命令》等等,而對檔案內容搜尋的命令似乎還沒有涉及,因此本文介紹文字搜尋命令--grep。
$ ps -ef|grep redis
ps -ef用於檢視系統程序情況,但是它列出的結果很多,如果我們只想看到自己需要的,則通過管道符,用grep進行過濾搜尋,例如搜尋redis相關的程序,最後它只會列出和redis相關的程序了:
$ ps -ef|grep redis
root 10748 10733 0 21:14 pts/21 00:00:00 redis-server *:6379
root 10754 10733 0 21:14 pts/21 00:00:00 grep --color=auto redis
那麼如果要排除某些不相關資訊呢?我們可以使用-v引數
$ ps -ef|grep redis |grep -v auto
root 10748 10733 0 21:14 pts/21 00:00:00 redis-server *:6379
這樣一來,包含auto相關的結果就不會出現在最終結果裡了。
如果只想統計結果數量呢?我們可以結合-c(count)引數:
$ ps -ef|grep redis -c
2
好了,說完了最常見的用法,我們來看看如何搜尋檔案內容。實際上awk和sed在這方面也頗有經驗,不過本文的主角是grep,所以另外兩個命令暫時不涉及。我們來看幾個例項。
例如,要在linux_command_debug.md檔案中,查詢test字串:
$ grep "test" aaa/bbb/linux_command_debug.md
int test(int a,int b)
test(a,b);
如果想要顯示指定關鍵字的行號,可以使用-n引數,例如:
$ grep -n "test" aaa/bbb/linux_command_debug.md
18:int test(int a,int b)
27: test(a,b);
前面提到了對乙個檔案內容進行搜尋,如果是多個呢?或者不想從某些檔案裡搜尋呢?
如果想對檔案進行指定也是可以的,例如搜尋所有的md結尾的檔案:
$ grep -n "test" *.md
或者可以使用--exclude引數來排除某些檔案,例如,查詢包含test,但是排除txt檔案:
$ grep -rn "test" --exclude=*.txt
搜尋時就會忽略.txt結尾的檔案了。
如果要排序的條件比較多,可以將要排除的條件儲存在另外乙個檔案裡:
$ grep -rn "test" --exclude-from=skip.txt
skip.txt的內容可以是模式匹配的檔名或者具體檔名:
*.txt
test.md
這樣,以.txt結尾,以及test.md檔案都不會搜尋了。
除此之外,還可以排除或指定目錄,它需要用到--exclude-dir引數:
$ grep -rn "test" --exclude-dir=aaa
它在搜尋時將會跳過aaa目錄下的檔案。
如果要在當前目錄下所有檔案查詢包含「int main(void)」字串的檔案:
$ grep -rn "int main(void)"
aaa/bbb/c_main_func.md:49:int main(void)
aaa/bbb/c_main_func.md:71:int main(void)
aaa/bbb/c_array.md:104:int main(void)
aaa/bbb/c_array.md:129:int main(void)
aaa/bbb/pc-lint.md:42:int main(void)
aaa/bbb/pc-lint.md:128:int main(void)
這可能是最實用的使用方法之一了。這裡-r引數表示遞迴查詢當前目錄的檔案,-n會顯示查詢位置的行號,如果只想顯示包含該指定關鍵字的檔名,可使用-l(--file-with-matches)引數:
$ grep -rln "int main(void)"
aaa/bbb/c_main_func.md
aaa/bbb/c_array.md
aaa/bbb/pc-lint.md
如果你嘗試一下就會發現,如果不帶-r引數,它會暫停,等待你從控制台輸入,例如:
$ grep -n "test"
test
1:test
所以使用時記得帶上相關引數奧!
前面提到了如何查詢包含某個字元的檔案,如果要找的是不包含該字元的檔案呢?
實際上只要使用-l引數即可:
$ grep -rln "int main(void)"
(這裡會顯示不包含指定關鍵字內容的檔名)
使用-i(--ignore-case)引數即可:
$ grep -rni "int main(void)"
aaa/bbb/c_main_func.md:49:int main(void)
aaa/bbb/c_main_func.md:71:int main(void)
aaa/bbb/c_array.md:104:int main(void)
aaa/bbb/c_array.md:129:int main(void)
aaa/bbb/pc-lint.md:42:int main(void)
aaa/bbb/pc-lint.md:128:int main(void)
前面的大部分例子都是顯示符合條件的行,如果要顯示不符合條件的行呢?可以用我們前面提到的-v引數:
$ grep -rnv "int main(void)"
(內容較多,未顯示)
從結果中就會發現,它會展示出包含指定關鍵字的檔案,但是展示的是不包含該字串的行。
假如你需要檢視包含指定關鍵字行附近的行,前面的方式是沒有辦法看到的,不過我們可以用-a(--after-context=)和-b(--before-context=)引數來顯示前後的行:
$ grep -rn "int main(void)" -a 1 -b 1
aaa/bbb/c_array.md-103-}
aaa/bbb/c_array.md:104:int main(void)
aaa/bbb/c_array.md-105-{
(其他內容省略)
通過最後加上-a和-b引數,顯示了指定關鍵字前面的行,這在日誌搜尋分析時非常有用。
如果有多個搜尋關鍵字怎麼處理呢?我們可以把關鍵字寫在乙個檔案,搜尋時指定檔案即可,例如規則檔案為key.txt:
int main(void)
test
從指定檔案中搜尋上面的關鍵字:
$ cat filename |grep -f key.txt
這樣結果就會顯示匹配key.txt檔案中所有關鍵字的行,非常適合用於多個條件的搜尋。
看完前面的內容,是不是還沒有感受到grep的強大,grep的另乙個強大之處是,它的搜尋支援正規表示式,例如查詢文字行以t開頭,以t結尾的檔案:
$ grep -rn ^t.*t$
key.txt:2:test
aaa/bbb/c_operate_redis_start.md:68:typedef struct stu_info_struct
aaa/bbb/c_operate_redis_start.md:101:typedef struct stu_info_struct
其中^t,表明以t開頭,t$表明以t結尾,如果需要使用擴充套件的正規表示式進行搜尋,可使用egrep命令。關於正規表示式的寫法,本文不做詳細介紹。
在內容搜尋方面,grep常常能夠助我們一臂之力,因此掌握grep的使用也是linux學習不可缺少的一部分,當然我們不需要完全記住每個引數的作用,但我們至少知道有這樣的引數,並且在需要時能夠快速查詢到。本文常用引數如下:
查詢字串
在乙個主串中查詢相應的子串,如 abcdwoshidef 中查詢 woshi 方法 該實現的方法是最簡單的模式匹配方法,時間複雜度較高 include iostream using namespace std int searchstring const char str1,const char s...
查詢字串
qstring startwith 判斷乙個字串是否以某個字串開頭,引數 字串,大小寫敏感 qstring str welcome to you str.startswith welcome qt casesensitive 返回true str.startswith you qt casesens...
查詢字串
本身不難,寫到這裡只是乙個備忘錄的作用。假定linux系統中有乙個目錄,其中遞迴的存在若干子目錄。現在需要在這些目錄的檔案中尋找乙個字串marvel。我看到的方法是 find type f exec grep marvel 可是死活就是錯誤 find missing argument to exec...