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