把簡單的技術學到極致就是高手。
前言
Linux三劍客指的是grep、sed以及awk命令的使用,這三個命令功能異常強大,大到沒朋友。grep命令主打“查找”,sed命令主打“編輯”,awk命令主打“分割處理”。之所以是28分鍾,大概是我比較嚴謹吧,數字也比較吉利。
下面給和網管相關的幾個例子看看實用的效果,改進建議也經常會用這些命令寫自動化腳本。如果以下例子秒懂,那不用看了,該干嘛干嘛。
1、掃描本地ip地址
ifconfig eth0 | grep "inet addr:" | awk '{print $2}' | sed 's/addr://g'
2、掃描端口號被哪個進程占用
netstat -anp | awk '{print $4,$7}' | grep 31006 | sed -n '1p' | awk '{print $2}' | awk -F'/' '{print $1}' | xargs ps -lfp | sed -n '2p' | awk '{print $17}'
3、獲取某個進程的堆棧
ps -elf | grep -v grep | grep necomm_agent | awk '{print $4}' | xargs gstack > yp.txt
4、批量重命名網元license備份的文件名
for i in `ls`; do mv -f $i `echo $i | sed 's/^[a-zA-Z0-9].*_[a-zA-Z0-9].*_\([0-9]\{8\}\)\(_\)\([0-9]\{6\}\)\(\.txt\)$/Lic_Esn_\1\2\3/'`; done
5、統計某個文件夾下的文件占用的字節數
ls -l | awk 'BEGIN {size=0;} {size = size + $5;} END{print “[end]size is ”, size/1024,1024, “M”}'
里面有幾個知識點先行贅述。
1、 何時需要xargs?
1) 有些命令本身是不支持管道,這個時候要加xargs,本身支持管道的命令有限如
cut grep sort uniq wc tee join split等
如下面的例子
echo "/opt" | ls -l //ls本身是不支持管道,所以對於前面管道輸出的內容會忽略,不會輸出/opt目錄下內容
echo "/opt" | xargs ls -l //加上xargs,執行的結果就是輸出/opt下目錄的內容
2) 命令雖然支持管道,但如果不加xargs和加xargs意義也截然不同。
比如網管中經常用到到在某個目錄下查找某個abc字符串:
find ./ | grep “abc” //這個命令不會在目錄下文件查找,而是把find出來的內容中查找,相當於在一群文件名中查找是否有包含abc的文件名。
find ./ | xargs grep "abc" //這個命令是把find出來的東西當做參數傳遞給管道后的內容,相當於在find出來的文件內容中查找是否包含字符串abc。
2、 正則表達式
一個正則表達式通常被稱為一個模式,用來描述或匹配一系列符合某個語法規則的字符串。正則表達式有多重不同的風格,但大同小異,下面列出PCRE中常用的元字符和意義。POSIX正則表達式分為基本正則表達式(BRE)和擴展表達式(ERE)。
目前很多UNIX工具程序沿用某一種正則表達式形式來強化本身的功能。常用的包括
1) grep工具組:grep和egrep
2) 改變輸入流的sed流編輯器
3) 字符串處理程序語言:awk
4) 文件查詢程序:more、less
5) 文本編輯器:vi
字符 |
意義 |
支持的類型 |
\ |
將下一個字符標記為特殊字符,或者將一個元字符轉義為普通字符。如n加上\匹配一個換行符。\\則匹配一個\字符。 |
BOTH |
^ |
匹配輸入字符串的開始位置 |
BOTH |
$ |
匹配輸入字符串的結束位置 |
BOTH |
* |
匹配前面的子表達式0次或者多次,如zo*能匹配z和zoo |
BOTH |
? |
匹配前面的子表達式0次或者1次 |
ERE |
. |
匹配除\n之外的任何單個字符 |
BOTH |
+ |
匹配前面的子表達式1次或者多次,如zo+能匹配zo和zoo,但不能匹配z |
ERE |
| |
匹配於|符號前或后的正則表達式 |
ERE |
{n,m} |
最少匹配n次,最多匹配m次和BRE的區別是不需要加\ |
ERE |
\{n\} |
匹配前面的子表達式n次 |
BRE |
\{n,\} |
至少匹配前面的子表達式n次 |
BRE |
\{n,m\} |
最少匹配n次,最多匹配m次 |
BRE |
\(\) |
將\(與\)間的模式存儲在特殊的保留空間 |
BRE |
\digit |
重復在\(與\)方括號內第n個子模式至此點的模式 |
BRE |
[xyz] |
匹配xyz中的任何一個字符 |
BOTH |
[^xyz] |
匹配未包含的任意字符 |
BOTH |
[x-z] |
匹配小寫的字符 |
BOTH |
如:
grep 'a\{3\}' test.txt \\查找test.txt中包含3個a的行
grep '^aa' test.txt \\查找test.txt中以aa開頭的行
grep ‘^$’ test.txt \\查找所有空行
后向引用
后向引用指的是“匹配於正則表達式匹配的先前的部分”。后向引用只在BRE中存在。使用后向引用的步驟有兩步。
1、 將子表達式包圍在\(與\)里,單個模式里可包含最多9個子表達式
2、 在模式之后使用\digit,digit是介於1至9的數字,指的是“匹配於第n個先前方括號內子表達式匹配成功的字符”
grep ‘\(why\).*\1’ test.txt \\一行里可以匹配why..why
grep ‘\(ab\)\(cd\)[def]*\2\1’ test.txt \\匹配abcddcdab
\< \>
匹配單詞的開頭與結尾。單詞是由字母、數字及下划線組成。
以下圖為各種UNIX程序與其使用的正則表達式
類型 |
Grep |
sed |
vi |
more |
egrep |
awk |
BRE |
√ |
√ |
√ |
√ |
|
|
ERE |
|
|
|
|
√ |
√ |
\< \> |
√ |
√ |
√ |
√ |
|
|
好,進入正題。
一、 grep命令
grep是一種強大的文本搜索工具,它能使用正則表達式搜索文本,並把匹配的行打印出來,其格式如下:
grep [選項] pattern file
常用的選項
-v 過濾指定字符串內容的行
-i 不區分大小寫
-n 順便打印出行號
-c 計算出符合行的次數
-E 默認grep只支持基本的正則表達式,加上-E支持擴展的正則表達式,grep –E和egrep意義一樣,擴展的正則表達式有’+’,’?’,’|’,’()’
常用的命令
ps –elf | grep –v grep | grep “necomm_agent” //如果不加grep –v grep,輸出2條內容
grep –i ‘abc’ test.txt//忽略大小寫,找出test.txt包含abc的行
grep –v ‘^$’ test.txt > testnew.txt //過濾test.txt的空行
二、 sed命令
sed是操作、過濾和轉換文本內容的強大工具,常用功能增刪改查,過濾,取行。
格式如下:
sed [options] [sed-commands] [input-file]
sed [選項] [sed命令] [輸入文件]
說明:
options常用的有:
-n :抑制默認輸出
-e 執行多條編輯命令
-i:直接在原文件中修改
sed-commands既可以是單個sed命令,也可以是多個sed命令組合
input-file(輸入文件)是可選項,sed還能夠從標准輸入如管道獲取輸入
工作原理
sed是從文件或管道中讀取一行,放在模式空間中,進行處理,處理完輸出一行;再讀取一行,再處理一行
模式空間:sed內部的一個臨時緩存,用於存放讀取到的內容
1)增
a 追加文本到指定行后
i 插入文本到指定行前
i 單行增加
sed '2a abc' test.txt
sed '2i abc' test.txt
ii 增加多行
sed '2a abc\
cde' test.txt
指定執行的地址范圍
sed可以對單行或多行進行處理,如果在sed命令前面不指定地址范圍,那么默認會匹配所有行。
用法 n1[,n2] {sed-commands}
地址用逗號分隔的,n1,n2可以是數字、正則表達式、或兩者的組合表示。$表示最后一行。
/abc/,/fff/{sed-commands} //對匹配abc的行到匹配fff的行操作
2)刪
d 刪除指定的行
sed '/aaa/d' test.txt
3)改
i c用新行取代舊行
sed '2c abc' test.txt
ii 文本替換
sed 's/abc/bcd/g' test.txt //后面的g代表全局替換,如果不加g,只替換每行第一個匹配的字符串
sed ‘s/^/abc /’ test.txt //在test.txt每行前插入abc
sed -i '/aaa/s/abc/bcd/g' test.txt //加上-i代表修改了文件test.txt
替換部分有幾個特殊的元字符,它們分別是
&:被pattern匹配的內容
\num:被pattern匹配的第num個分組(正則表達式的概念,\(…\)括起來的部分成為分組)
sed '/d/s/ab/&jj/' test.txt //將匹配d內容的行中的ab替換為abjj
echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/' //將命令中的digit 7 修改為7
4)查
p 輸出指定內容,但默認會輸出2次匹配的結果,因此使用n取消默認輸出
按行查詢
sed -n '2p' test.txt
按字符串查詢
sed –n ‘/abc/p’ test.txt
混合查詢
sed –n ‘2,/abc/p’ test.txt
5)多命令編輯
sed -e '1,5d' -e 's/test/check/' test.txt
三、awk命令
awk是一個強大的文本分析工具,相對於grep的查找,sed的編輯,awk在其對數據分析並生產報告時,顯得尤為強大。簡單的說就是把文件逐行的讀入,以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。
使用方法
awk [-F field-separator] '{pattern + action}' {filename}
pattern表示awk在數據庫中查找的內容,action表示找到匹配內容所執行的一系列命令,pattern就是要表示的正則表達式,用斜杠括起來。
-F 域分隔符 是可選的,如果不指定,默認的域分隔符是空格
awk '{print $1}'
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
執行流程為:先執行BEGIN,然后讀取文件,讀入有\n換行符分割的一條記錄,然后將記錄按指定的域分隔符划分域,填充域,$0表示所有域,$1表示第一個域,$n表示第n個域,隨后開始執行模式所對應的動作action。
然后開始讀入第二條記錄.....直到所有的記錄都讀完,最后執行END操作
常用的命令
awk -F: '/^root/' /etc/passwd 如果沒有指定action,默認輸出每行的內容
awk -F: '/^ftp/{print $4}' /etc/passwd 指定了action
ls -l|awk '/^[^d]/ {print $9"\t"$5} {tot+=$5} END{print "totKB:" tot}'
統計某個文件夾下的文件占用的字節數
ls -l | awk 'BEGIN {size=0;} {size = size + $5;} END{print “[end]size is ”, size/1024,1024, “M”}'
awk的編程是從C語言借鑒過來的,所以語法類似
如test.txt中包含姓名和各科成績,輸出姓名和最大成績
awk 'BEGIN {MAX=0;} {NAME = $1; for(x=2; x<=NF; x++) { if($x >= MAX) { MAX=$x}} printf "name:%s MAX:%d\n", NAME,MAX; MAX=0}' test.txt