Linux 三劍客是(grep,sed,awk)三者的簡稱,熟練使用這三個(gè)工具可以提升運(yùn)維效率。Linux 三劍客以正則表達(dá)式作為基礎(chǔ),而在Linux系統(tǒng)中,支持兩種正則表達(dá)式,分別為“標(biāo)準(zhǔn)正則表達(dá)式”和“擴(kuò)展正則表達(dá)式”。在掌握好正則表達(dá)式后,將具體講解三劍客的用法。
正則表達(dá)式:REGular EXPression, REGEXP元字符:.: 匹配任意單個(gè)字符[]: 匹配指定范圍內(nèi)的任意單個(gè)字符[^]:匹配指定范圍外的任意單個(gè)字符 字符集合:[:digit:], [:lower:], [:upper:], [:punct:], [:space:], [:alpha:], [:alnum:] 注意:字符集合要用[ ]包含匹配次數(shù)(貪婪模式):*: 匹配其前面的字符任意次 a, b, ab, aab, acb, adb, amnb a*b, a?b a.*b .*: 任意長度的任意字符\?: 匹配其前面的字符1次或0次\ :匹配至少一次\{m,n\}:匹配其前面的字符至少m次,至多n次 \{1,\} \{0,3\} 備注:至少0次,必須要顯示的寫出來。位置錨定:^: 錨定行首,此字符后面的任意內(nèi)容必須出現(xiàn)在行首$: 錨定行尾,此字符前面的任意內(nèi)容必須出現(xiàn)在行尾^$: 空白行\(zhòng)<或\b: 錨定詞首,其后面的任意字符必須作為單詞首部出現(xiàn)\>或\b: 錨定詞尾,其前面的任意字符必須作為單詞的尾部出現(xiàn)分組:\(\) \(ab\)* 后向引用 \1: 引用第一個(gè)左括號(hào)以及與之對(duì)應(yīng)的右括號(hào)所包括的所有內(nèi)容 \2: \3:
可以看到標(biāo)準(zhǔn)正則表達(dá)的使用過程中,許多符號(hào)都需要轉(zhuǎn)義,這在工作中帶來了一定的不便,因此擴(kuò)展的正則表達(dá)式便出現(xiàn)了。
1. 字符匹配:.[abc]:包含abc任意一個(gè)字符[^abc]:不包含abc任意一個(gè)字符2. 次數(shù)匹配(不用再轉(zhuǎn)義):*: ?: : 匹配其前面的字符至少1次{m,n}3. 位置錨定:^$\<\>4. 分組(不用再轉(zhuǎn)義):():分組\1, \2, \3, ...5. 或者|: orC|cat: C或cat(表示的是整個(gè)部分)
可以看到,使用擴(kuò)展的正則表達(dá)式可以省略很多的轉(zhuǎn)義符號(hào),這尤其在寫sed語句時(shí)極大的提高了代碼的可讀性。建議優(yōu)先使用擴(kuò)展的正則表達(dá)式。
grep命令家族由grep, egrep, fgrep 三個(gè)子命令組成,適用于不同的場景。具體如下:
命令 描述
grep 原生的grep命令,使用“標(biāo)準(zhǔn)正則表達(dá)式”作為匹配標(biāo)準(zhǔn)。
egrep 擴(kuò)展的grep命令,相當(dāng)于$(grep -E),使用“擴(kuò)展正則表達(dá)式”作為匹配標(biāo)準(zhǔn)。
fgrep 簡化版的grep命令,不支持正則表達(dá)式,但搜索速度快,系統(tǒng)資源使用率低。
語法
grep [options] PATTERN [FILE...]
options部分
-i:忽略大小寫
--color:高亮匹配上的字符串
-v: 顯示沒有被模式匹配到的行
-o:只顯示被模式匹配到的字符串
-E:使用擴(kuò)展的正則表達(dá)式
PATTERN部分
以字符串的方式給定匹配模板,可以使用普通字符串以及正則表達(dá)式(標(biāo)準(zhǔn)&擴(kuò)展)。
FILE部分
需要查找內(nèi)容的文件。
sed全稱是Stream EDitor
sed是一個(gè)流編輯器、行編輯器
sed [option] 'script' [input file]...
option部分
-n:不輸出模式空間中的內(nèi)容到stdout
-e:可以在sed命令中指定多個(gè)script腳本,多點(diǎn)編輯功能
-f:輸入sed腳本,腳本中寫著編輯命令
-r:支持使用擴(kuò)展的正則
-i:直接編輯源文件
script部分
地址定界編輯命令(和vim命令相似)
1)空地址:全文編輯
2)單地址:
? #:指定某一行,對(duì)特定行進(jìn)行編輯
? /pattern/:指定模式匹配到的那一行
3)地址范圍:
? #,#
? #, #
? #,/pattern/
? /pattern1/,/pattern2/
4)步進(jìn)地址:
? 1~2:以1為起始行,然后遞進(jìn)2行向下匹配
? 2~2:所有偶數(shù)行
5)編輯命令:
? d:刪除整行,d放在最后
? p:顯示模式空間中的內(nèi)容, 放在最后
? a:在匹配的行后面增加文本,使用\n支持多行追加。a放在定界后面
? i:在前面加文本。舉例:sed '3i hello' xxx
? c:替換行為指定的文本。舉例:sed '3c text' xxx 把第三行替換成text。sed -i '/xyz/c helloworld' num.txt
? w:保存模式空間中匹配的內(nèi)容到指定位置。舉例:sed -n '/^[^#]/w /tmp/demo' /etc/fstab 將/etc/fstab中非#開頭的行保存到/tmp/demo中。
? r:讀取指定文件的內(nèi)容添加到當(dāng)前文件匹配到的行后面,進(jìn)行文件合并。
? ?。簵l件取反。用法:地址定界!編輯命令。
? s///:條件替換。
替換標(biāo)記備注:g(全局替換),p(顯示替換成功的行)
替換舉例:根據(jù)輸入查找目錄
echo "/var/log/messages" | sed 's@[^/] $/?@@'
模式空間與保持空間
在模式空間中,完成匹配的操作。當(dāng)沒有匹配上的時(shí)候,文本行內(nèi)容會(huì)默認(rèn)輸出stdout;當(dāng)匹配上文本行的時(shí)候,會(huì)執(zhí)行編輯命令,執(zhí)行結(jié)果輸出到stdout中。
保持空間可以理解為一個(gè)暫存區(qū),只是用于完成額外的動(dòng)作。
參數(shù)
h:把模式空間中的內(nèi)容覆蓋至保持空間中;
H:把模式空間中的內(nèi)容追加至保持空間中;
g:把保持空間中的內(nèi)容覆蓋至模式空間中;
G:把保持空間中的內(nèi)容追加至模式空間中;
x:把模式空間中的內(nèi)容與保持空間中的內(nèi)容互換;
n:覆蓋讀取匹配到的行的下一行(改變指向)至模式空間中;
N:追加讀取匹配到的行的下一行(改變指向)至模式空間中;
d:刪除模式空間中的行;
D:刪除多行模式空間中的所有行;
3. 舉例sed -n 'n;p' FILE:顯示偶數(shù)行;sed '1!G;h;$!d' FILE:逆序顯示文件的內(nèi)容;sed '$!d' FILE:取出最后一行;sed '\$!N;$!D' FILE:取出文件后兩行;sed '/^$/d;G' FILE:刪除原有的所有空白行,而后為所有的非空白行后添加一個(gè)空白行;sed 'n;d' FILE:顯示奇數(shù)行;sed 'G' FILE:在原有的每行后方添加一個(gè)空白行;
舉例:提取字符串
/bin/bashinfo="hellozimskyshenzhen"echo $info | sed 's/hello\(\w\ \)shenzhen/\1/g'
備注:
sed中不支持\d,如果要用數(shù)字用[0-9],但是支持\w。
sed中的()要轉(zhuǎn)義, 要轉(zhuǎn)義,<>大于小于號(hào)要轉(zhuǎn)義。
舉例:判斷是否存在指定格式的字符串
#!/bin/bash# 判斷輸入是否為整數(shù)if [ -n "$(echo $1 | sed -n '/^[0-9]\ $/p')" ] ; then echo 'yes'else echo 'no'fi
awk是發(fā)明該工具三個(gè)作者姓名的首字母簡稱,awk是一個(gè)報(bào)表生成器,主要用于格式化輸出。格式化文本輸出器。
1. 語法
gawk [option] 'program' FILE
其中program: PATTERN{ACTION STATEMENTS}
{動(dòng)作指令}可以理解成為命令,最常用的是print、printf
2. awk讀取文檔過程
按照行來讀取文檔,根據(jù)輸入分隔符切分成小部分(用內(nèi)建變量來表示$0$1$2...),用ACTION STATEMENTS來處理。$0表示顯示整行。
3. 選項(xiàng)option
-F:指名輸入字段的分隔符;
-v:用來實(shí)現(xiàn)自定義變量var=value;
4. PATTERN(用于定界)
?空:表示處理文件的每一行
?/pattern/:使用正則匹配需要處理的行
?!/pattern/:上面取反
?關(guān)系表達(dá)式:結(jié)果為真假,結(jié)果為真的處理,假的不處理。非0非空字符串為真,其余為假。
?行定界:不支持直接給出數(shù)字的格式(1,2{...})。見舉例。
?BEGIN/END模式:BEGIN{}表示僅在開始處理文件中的文本之前執(zhí)行一次的程序,例如打印表頭。END{}表示文本處理完成之后執(zhí)行一次,例如匯總數(shù)據(jù)。
舉例:awk -F: '$NF=="/bin/bash" {print $1, $NF}' /etc/passwdawk -F: '$NF!"/bash/$"{print $1,$NF}' passwdawk -F: '$3<1000 {print $1, $3}' /etc/passwdawk -F; '(NR>=2&&NR<=10){print $1}' /etc/passwd 行定界awk -F: '{printf "%-15s s\n", $1, $2}' /etc/passwd
5. 變量
內(nèi)建變量(在引用變量時(shí)不用加$)
FS:input field seperator:輸入字段分隔符,默認(rèn)空白字符。使用-v指定。
OFS:輸出字段分隔符。使用-v指定。
RS:輸入時(shí)的換行符
ORS:輸出時(shí)的換行符
NF:number of field 每一行的字段數(shù)量。加上$NF表示最后一列。
NR:number of record 文件的行數(shù),打印出來是打印行號(hào)
FNR:多個(gè)文件中的行數(shù)分別計(jì)數(shù)
FILENAME:當(dāng)前文件的文件名
ARGC:參數(shù)命令行中參數(shù)的個(gè)數(shù)
ARGV:返回?cái)?shù)組,命令行中的每個(gè)參數(shù)
舉例:awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/issue
在這里ARGV[0]是awk,固定為第0個(gè)參數(shù)。ARGV[1]是/etc/fstab,ARGV[2]是/etc/issue
舉例:awk -v FS=':' '{print $1}' -v OFS=':' /etc/passwd 指名冒號(hào)作為輸入的分隔符。同awk -F: ...
自定義變量
方法1:-v var=value (區(qū)分字符的大小寫)
方法2:在program中定義
舉例:awk -v test='hello' 'BEGIN {print test}'
awk 'BEGIN {test='hello' print test}'
6. 常用的ACTION命令
print
輸出格式:print item1,item2 ...
備注:使用逗號(hào)作為分隔符;輸出item可以是字符串、內(nèi)建變量、awk表達(dá)式;若省略item,則顯示$0整行;
printf
格式化輸出:printf FORMAT, item1, item2...按位放在format中。
注意事項(xiàng):format必須要給出;如需換行,必須要顯示寫出;format中需要為后面每個(gè)item指定格式符;
Expressions
Control statements:控制語句if,while
if(condition){statement}
if(condition){statement} else {statements}
while(condition) {statements}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array[index]
delete array刪除整個(gè)數(shù)組
exit 退出語句
Compound statements:組合語句
Input statements:輸入語句
Output statements:輸出語句
格式符:
?%c:顯示字符的ASCII值
?%d:顯示十進(jìn)制整數(shù)
?%e:科學(xué)計(jì)數(shù)法數(shù)值顯示
?%f:顯示為浮點(diǎn)數(shù)
?%g:以科學(xué)計(jì)數(shù)法顯示浮點(diǎn)數(shù)
?%s:顯示字符串
?%u:顯示無符號(hào)整數(shù)
?%%:顯示%自身
修飾符:
?#[.#]:第一個(gè)數(shù)字用于控制顯示字符的寬度,第二個(gè)數(shù)字表示小數(shù)的精度(對(duì)于浮點(diǎn)數(shù)而言);輸出默認(rèn)右對(duì)齊s,左對(duì)齊:%-15s; :表示帶正負(fù)符號(hào);
操作符:
?算數(shù)操作符: -/* ; x把字符串轉(zhuǎn)換成數(shù)值;-x改成負(fù)數(shù);
?字符串操作符:字符串連接(沒有操作符)
?復(fù)制操作符:=, =,-=,/=, ,--
?比較操作符:>,<,<=,!=,==
模式匹配符:
?~:左側(cè)的字符串是否被模式匹配
?!~:左側(cè)的字符串是否不能被模式匹配
邏輯操作符:
?&&:與
?||:或
?!:非
函數(shù)調(diào)用:
?function_name(arg1, arg2, ...)
條件表達(dá)式:
?selector?true_exp:false_exp 和三目運(yùn)算符一樣
操作例子
# 一般來說, 打印無狀態(tài)內(nèi)容放在BEGIN和END塊中awk -v begin="hello" -v end="ok" -F: 'BEGIN{print begin}; {print $1, $NF}; END{print end}' /etc/passwd
awk常用內(nèi)置變量
$1:表示第一列$NF:表示最后一列$NR:表示行號(hào)
常用條件表示
1) /指定內(nèi)容/
這種方式可以匹配到含有“指定內(nèi)容”的行,在條件中不添加$#所帶的項(xiàng),建議不使用正則,有異常情況。
awk -F: '/nologin/{print $0}' /etc/passwd #匹配到含有nologin關(guān)鍵字的行seq 100 | awk '/1/{print $1}'
2) $#=/指定內(nèi)容/
這種方式指定第#列匹配指定內(nèi)容
awk -F: '$1=/bin/{print $0}' /etc/passwd
3) $#~/指定內(nèi)容/
這種方式用于指定列模糊匹配(正則匹配)指定內(nèi)容,并獲取該行。
awk -F: '$1~/dae/{print $1}' /etc/passwd #正向選擇awk -F: '$1!~/dae/{print $1}' /etc/passwd #反向選擇
4) 值判斷
使用>,<,>=,<=,==,!=來判斷指定列的值。
awk -F: '$3>=10{print $1}' /etc/passwd
5) 邏輯判斷
使用&&,||來進(jìn)行邏輯判斷。
awk -F: '$3>=5 && $3<=10{print $1}' /etc/passwd
6) if條件判斷
awk -F: '{if ($NF~/nologin$/){i }else{j }}; END{print i, j}' /etc/passwd#注意if-else條件判斷是放在{}中的
7) 字典使用
在awk中可以定義數(shù)組類型,用于統(tǒng)計(jì)。
awk '{ip[$1] }; END{for (i in ip) {print i, ip[i]}}' access.log#解析: 將第一列ip設(shè)置為字典的key,當(dāng)出現(xiàn)一次相同的ip時(shí)自增1,用于統(tǒng)計(jì)所有的ip計(jì)數(shù)。#for循環(huán)中取到每個(gè)字典對(duì)應(yīng)的key,再使用print塊打印出來。注意花括號(hào)的隔離。
#QQ號(hào) 等級(jí) 時(shí)長#統(tǒng)計(jì)等級(jí)(30<=x<=90),相同賬號(hào)的時(shí)長#1234 12 23#1234 10 122#1233 92 4212#1233 42 4252#1239 87 2313#1233 56 1121#1231 19 45#1235 45 679cat data | awk '$2>=30&&$2<=90{dic[$1] =$3}; END{for (i in dic) {print i, dic[i]}}'
聯(lián)系客服