Linux上文本處理三劍客: mysql
grep:文本過濾(模式:pattern)工具;linux
grep:支持基本的正則表達式nginx
egrep:支持擴展的正則表達式正則表達式
fgrep:不支持正則表達式sql
sed:stream editor,文本編輯工具,也叫行編輯器;shell
awk:Linux上的實現gawk,文本報告生成器;express
grep:文本過濾器編程
grep: Global search REgular expression and Print out the line.數組
做用:文本搜索工具,根據用戶指定的「模式」對目標文本逐行進行匹配檢查;打印匹配到的行;bash
模式:支持正則表達式引擎,由正則表達式字符及文本字符所編寫的過濾條件;
正則表達式(REGEXP):由一類特殊字符及文本字符所編寫的模式,其中有些字符不表示字符字面意義,而表示控制或通配的功能;
分兩類:
基本正則表達式:BRE
擴展正則表達式:ERE
grep -E, egrep
參考:http://www.javashuo.com/article/p-nftostxv-bm.html
語法:grep [OPTIONS] PATTERN [FILE...]
OPTIONS:
--color=auto: 對匹配到的文本着色顯示;
-v: 顯示不可以被pattern匹配到的行;
-i: 忽略字符大小寫;
-o: 僅顯示匹配到的字符串;
-q: 靜默模式,不輸出任何信息;
-A #:after, 後#行
-B #: before, 前#行
-C #:context, 先後各#行
-E, --extended-regexp:使用ERE(Extended Regular Expression);
fgrep:不支持正則表達式搜索;
sed:編輯器
sed: Stream EDitor, 行編輯器;
sed命令兩個內在空間:
1. 模式空間(pattem space):一段內存空間,可理解爲行數據處理車間。sed一次處理一行數據,將要處理的數據拷貝至模式空間中進行處理,處理後默認將結果輸出到屏幕;
2. 保持空間(hold space):可理解爲行半成品倉庫。當模式空間中的數據尚未處理完須要處理其它行的時候,就將該行數據從模式空間移動至保持空間,當模式空間中的數據處理完畢後再將保持空間中的數據讀取至模式空間再次處理;
基本工做機制:
從一個文本文件中依次(若未使用地址定界)只讀取一行數據到Sed的模式空間中,基於給定的編輯腳本對模式空間中的內容進行編輯處理,以後將編輯後的結果(或未編輯的結果)默認輸出到屏幕;sed在讀取一行後不會作原地編輯。
語法:
sed [option]... 'script' inputfile...
script: '地址命令'
經常使用選項:
-n:不輸出模式空間中的內容至屏幕;
-e: 多點編輯;
-f /PATH/TO/SCRIPT_FILE: 從指定文件中讀取編輯腳本;
-r: 支持使用擴展正則表達式;
-i: 原處編輯;
地址定界(要處理的行):
(1) 不給地址:對全文進行處理;
(2) 單地址:
#: 指定的行;
/pattern/:被此處模式所可以匹配到的每一行;
(3) 地址範圍:
#,#:如:m,n表示m行開始至n行結束
#,+#:如:m,+n表示從m行開始,下走n行結束
/pat1/,/pat2/:從pat1匹配的行開始至pat2行結束
#,/pat1/:從#行開始至pat1匹配的行結束
(4) ~:步進
1~2:讀全部奇數行,讀第1行,步進2;
2~2:讀全部偶數行,讀第2行,步進2;
編輯命令:
d: 刪除
p: 顯示模式空間中的內容
a \text:在行後面追加文本;支持使用\n實現多行追加;
i \text:在行前面插入文本;支持使用\n實現多行插入;
c \text:替換行爲單行或多行文本;
w /path/to/somefile: 保存模式空間匹配到的行至指定文件中;
如:將fstab中UUID開頭的行另存爲至/tmp/fstab: # sed '/^UUID/w /tmp/fstab' /etc/fstab
r /path/from/somefile:讀取指定文件的文本流至模式空間中匹配到的行的行後;
=: 爲模式空間中的行打印行號;
!: 取反條件(對地址定界);
s///:支持使用其它分隔符,s@@@,s###;
替換標記:
g: 行內全局替換;
p: 顯示替換成功的行;
w /PATH/TO/SOMEFILE:將替換成功的結果保存至指定文件中;
練習:
刪除/etc/fstab文件中以UUID開頭的行:
$ sed '/^UUID/d' /etc/fstab
僅顯示/etc/fstab中以UUID開頭的行:
$ sed -n '/^UUID/p' /etc/fstab
在fstab文件中每一個以UUID開頭的行下方追加行「## Hello Sed」:
$ sed '/^UUID/a \## Hello Sed.' fstab
在fstab文件中每一個以UUID開頭的行上方追加一行「newline」:
$ sed '/^UUID/i newline' fstab
將fstab文件中以UUID開頭的行替換爲「## Hello Sed.」
$ sed '/^UUID/c ## Hello Sed.' fstab
將f1.txt文件中以E:開頭的行另存至mmm.txt文件中:
$ sed '/^E:/w mmm.txt' f1.txt
讀取/etc/issue文件插入至fstab文件的第6行下方:
$ sed '6r /etc/issue' fstab
只保留fstab文件中以UUID開頭的行:
$ sed '/^UUID/!d' fstab
查找fstab文件中以UUID開頭的行,並將UUID替換爲uuid:
$ sed '/^UUID/s/UUID/uuid/c' fstab
查找/etc/passwd文件中,以r開頭間隔兩個任意字符後以t結尾的字符串,所有引用並追加er後進行替換之,只之打印更改的內容:
$ sed -n 's/r..t/&er/gp' /etc/passwd rooter:x:0:0:rooter:/rooter:/bin/bash nm-open***:x:119:127:NetworkManager Open×××,,,:/var/lib/open***/chrooter:/bin/false
刪除/boot/grub/grub.conf文件中全部以空白開頭的行行首的空白字符;
~]# sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
刪除/etc/fstab文件中全部以#開頭,後面至少跟一個空白字符的行的行首的#和空白字符;
~]# sed 's@^#[[:space:]]\+@@' /etc/fstab
echo一個絕對路徑給sed命令,取出其基名;取出其目錄名;
取目錄名,搜索一個以上非路徑分隔符,後跟一個無關緊要的路徑分隔符結尾,替換爲無:
~]# echo "/etc/sysconfig/" | sed 's@[^/]\+/\?$@@' /etc/
取基名:
$ echo "/etc/sysconfig/" | sed -nr 's@.*/(.+)/?@\1@p'sysconfig/ $ echo "/etc/sysconfig/abc" | sed -nr 's@.*/(.+)/?@\1@p'abc
or
$ echo "/etc/sysconfig/" | sed -nr 's@(.*/)(.+)/?@\2@p' sysconfig/ $ echo "/etc/sysconfig/abc" | sed -nr 's@(.*/)(.+)/?@\2@p' abc
高級編輯命令:
h: 把模式空間中的內容覆蓋至保持空間中;
H:把模式空間中的內容追加至保持空間中;
g: 從保持空間取出數據覆蓋至模式空間;
G:從保持空間取出內容追加至模式空間,保持空間中的內容會追加到模式空間中內容的下方;
x: 把模式空間中的內容與保持空間中的內容進行互換;
n: 讀取匹配到的行的下一行至模式空間,原模式空間中的內容將會被覆蓋;
N:追加匹配到的行的下一行至模式空間,原模式空間中的內容不變;
d: 刪除模式空間中的行;
D:刪除多行模式空間中的全部行;
多條編輯命令用「分號」隔開;
列舉高級編輯命令用法:
逆向顯示文件中的每一行;
sed -n '1!G;h;$p' FILE:
解析:這是三個命令:
1:讀取第1行時:
(1)不執行任何操做;
(2)把第1行追加到保持空間中;
(3)由於不是最後一行,因此不執行打印操做;
2:讀取第2行時:
(1)從保持空間中讀取第1行,覆蓋至模式空間,此時模式空間中爲第1行;
(2)將模式空間中的第二、1行覆蓋至保持空間,此時模式空間和保持空間都是二、1行;
(3)由於不是最後行不執行打印操做;
3:讀取第3行(最後行):
(1)讀取第3行覆蓋至模式空間,並從保持空間讀取第二、1行追加至模式空間,此時模式空間爲三、二、1行;
(2)把模式空間中的內容覆蓋至保持空間,此時保持空間也爲三、二、1行;
(3)由於當前行是最後行,因此打印模式空間中的內容至屏幕,三、二、1行。
顯示偶數行:
sed -n 'n;p' FILE
or
sed -n '2~2p' FILE
逆向顯示文件內容
sed '1!G;h;$!d' FILE
解析:
(1)若是讀取的不是第一行,則將保持空間中的內容追加至模式空間;
(2)把模式空間中的內容覆蓋至保持空間中;
(3)若是讀取的不是最後一行則刪除模式空間中的內容
取出文件後兩行:
sed '$!N;$!D' FILE
取出文件最後一行:
sed '$!d' FILE
每行後邊增長一個空白行:
sed 'G' FILE
解析:讀取每一行時都從保持空間中讀取空白行追加至模式空間,並把模式空間中的內容打印出來
每行後面增長一個空白行,若是有連續多個空白行則合併爲一個;
sed '/^$/d;G' FILE
解析:讀取某行時若是是空白行,則刪除,再增長一個空白行,若是不是空白行則第一個命令不知足,直接執行第二個命令,當前行下追加一個空白行
顯示奇數行:
sed 'n;d' FILE
or
sed -n '1~2p' FILE
awk: 報告生成器
awk:Unix/Linux下的報告生成器,用來實現格式化文本輸出;
awk: 其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母,Unix下的文本處理工具,通過改進生成的新的版本nawk(New AWK),後來在Linux下得以實現,名爲gawk(GNU awk),但由於人們已經習慣用awk來命名,因此awk得以繼續使用,在某些Linux發行版上能夠發現awk爲gawk的別名或連接。
gawk - pattern scanning and processing language,模式掃描及處理語言,一種編程語言的解釋器,本質上是一種腳本編程語言
基本用法:
gawk [options] 'program' FILE ...
options:
-F:指明輸入時用到的字段分隔符;
-v var=value: 自定義變量;
program: PATTERN{ACTION STATEMENTS}
PATTERN:地址定界模式,指定對哪些文本行進行處理。好比以「UUID」開頭的行
ACTION STATEMENTS:處理語句,語句之間用分號分隔,指明對指定的文本行如何處理。 如經常使用語句print和printf
工做機制:
1. 從指定的文件中一次讀取一行文本,以後以指定的輸入分隔符(默認爲空白字符)進行切片,把一行文本分紅N個片段,每一個片段都直接保存到awk內建的變量中,這些變量中第1個變量(保存了第一段文本)叫$1,第2個變量叫$2,第三個變量叫$3,以此類推,$0表示事行文本。一行文本被切割成多段後能夠僅顯示諸多片斷中的某一段、某些段或所有段。
2. 一行文本被切割成多段後,能夠對每一段文本進行判斷或處理。好比判斷每一行的第2段是否在某個數值範圍內,若是在就把該行的第4段顯示出來,也能夠對一行文本的每一段進行循環(同一行各字段間)處理。
處理語句(ACTION STATEMENTS):
一、print
語法:print item1, item2, ...
要點:
(1) 要輸出的多字段間以逗號分隔符進行分隔,最終顯示的結果默認爲空格分隔符;
(2) 輸出的各item能夠字符串,也能夠是數值(輸出時隱式轉換成字符串進行輸出);當前記錄的字段、變量或awk的表達式;
(3) 如省略item,至關於print $0,即打印整行;
Example:
打印/etc/passwd文件中最後3行的第1段和第3段:
$ tail -n3 /etc/passwd | awk -F: '{print $1,$3}' usbmux 122 yinkai 1000 mysql 123
打印/etc/passwd文件中最後3行的用戶名和UID:
$ tail -n5 /etc/passwd | awk -F: '{print "User:",$1," UID:",$3}' User: usbmux UID: 122 User: yinkai UID: 1000 User: mysql UID: 123
打印/etc/passwd文件中最後3行:
$ tail -n3 /etc/passwd | awk '{print}' usbmux:x:122:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false yinkai:x:1000:1000:Yinkai,,,:/home/yinkai:/bin/bash mysql:x:123:132:MySQL Server,,,:/nonexistent:/bin/false
二、變量
2.1 內建變量:在引用內建變量時無需加「$」
FS:input Field Seperator(輸入分隔符),默認爲空白字符;
OFS:Output Field Seperator(輸出分隔符),默認爲空白字符;
Example:
# awk -v FS=':' -v OFS='---->' '{print $1,$3,$7}' /etc/passwd root---->0---->/bin/bash bin---->1---->/sbin/nologin daemon---->2---->/sbin/nologin adm---->3---->/sbin/nologin lp---->4---->/sbin/nologin sync---->5---->/bin/sync
RS:input Record Seperator,輸入時的換行符;
ORS:output record seperator,輸出時的換行符,補充的輸出換行符,原有的換行符依然有效;
Example:
使用空白符做爲輸入換行符,使用‘ && ’做爲輸出換行符,顯示/etc/passwd文檔內容
$ awk -v RS=' ' '{print}' /etc/passwd usbmux:x:122:46:usbmux && daemon,,,:/var/lib/usbmux:/bin/false yinkai:x:1000:1000:Yinkai,,,:/home/yinkai:/bin/bash mysql:x:123:132:MySQL && Server,,,:/nonexistent:/bin/false
NF:Number of Field,每行的字段數量
{print NF}:打印每行的字段數
{print $NF}:打印每行的最後一個字段
Example:
以‘:’爲分隔符,顯示/etc/passwd文件最後一行的字段數:
$ tail -n1 /etc/passwd | awk -v FS=':' '{print NF}' 7
取/etc/passwd的基名:
$ ll /etc/passwd | awk -v FS='/' '{print $NF}' passwd
NR:Number of Record, 行數;對文件的行進行記數,若是指定多個文件則合併記數。
FNR:File Number of Record, 各文件分別計數;行數;
Example:
統計/etc/{fstab,issue}這兩個文件的總行數:
$ awk '{print NR}' /etc/{fstab,issue} | tail -n1 21
FILENAME:當前文件名;
Example:
分別統計/etc/{resolv.conf,issue}兩個文件的行數:
$ awk '{print FILENAME,"-->",FNR}' /etc/{resolv.conf,issue} /etc/resolv.conf --> 1 /etc/resolv.conf --> 2 /etc/resolv.conf --> 3 /etc/issue --> 1 /etc/issue --> 2
ARGC:命令行參數的個數;
ARGV:是一個數組,數組內保存的是命令行所給定的各個參數;
Example:
1. 顯示該awk命令中各參數的總數(包含awk命令自身):
$ awk 'BEGIN{print ARGC}' /etc/{resolv.conf,issue} 3
2.分別顯示該awk命令中各個參數,ARGV[0]返回的是數組中第0個參數:
$ awk 'BEGIN{print ARGV[0]}' /etc/{resolv.conf,issue} awk $ awk 'BEGIN{print ARGV[1]}' /etc/{resolv.conf,issue} /etc/resolv.conf $ awk 'BEGIN{print ARGV[2]}' /etc/{resolv.conf,issue} /etc/issue
2.2 自定義變量
(1) -v var=value
變量名區分字符大小寫;
(2) 在program中直接定義
Example:
# awk -v test='Hello GAWK' 'BEGIN{print test}' Hello GAWK
或
# awk 'BEGIN{test="Hello GAWK";print test}' Hello GAWK
這兩行功能相同。
三、printf命令
格式化輸出:printf FORMAT, item1, item2, ...
(1) FORMAT是格式佔位符,用於爲後邊的item指定輸出格式,必須給出;
(2) 不會自動換行,須要顯式給出換行控制符,\n
(3) FORMAT中須要分別爲後面的每一個item指定一個格式化符號;
格式符:
%c: 顯示字符的ASCII碼;
%d, %i: 顯示十進制整數;
%e, %E: 科學計數法數值顯示;
%f:顯示爲浮點數;
%g, %G:以科學計數法或浮點形式顯示數值;
%s:顯示字符串;
%u:無符號整數;
%%: 顯示%自身;
修飾符:
\t: table製表符;
\n:空格
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後的精度;
%3.1f
-: 左對齊
+:顯示數值的符號
Example:
顯示/etc/passwd最後三行的用戶名和UID:
$ awk -F: '{printf "Username: %s, UID: %d\n",$1,$3}' /etc/passwd | tail -n3 Username: usbmux, UID: 122 Username: yinkai, UID: 1000 Username: mysql, UID: 123
# awk -F: '{printf "Username: %-15s \tUID:%i\n",$1,$3}' /etc/passwd | head Username: root UID:0 Username: bin UID:1 Username: daemon UID:2 Username: adm UID:3 Username: lp UID:4 Username: sync UID:5 Username: shutdown UID:6 Username: halt UID:7 Username: mail UID:8 Username: operator UID:11
四、操做符
算術運算操做符:
x+y, x-y, x*y, x/y, x^y, x%y
-x:將正數轉換爲負數的單目運算符;
+x: 轉換爲數值;
字符串操做符:沒有符號的操做符,字符串鏈接
賦值操做符:
=, +=, -=, *=, /=, %=, ^=
++:自加運算符
--:自減運算符
比較操做符:
>, >=, <, <=, !=, ==
Example: 打印默認shell爲bash的用戶名和shell:
# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd root /bin/bash bash /bin/bash testbash /bin/bash
模式匹配符:
~:左側的字符串是否能被右側的模式所匹配
Example: 打印默認shell爲bash的用戶:
# awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd #打印$NF的值匹配bash$這個模式的行,模式需用斜線括起來。 root /bin/bash tom /bin/bash jerry /bin/bash nginx /bin/bash
!~:左側的字符串是否不能被右側的模式所匹配
Example: 打印默認shell爲bash的用戶名和shell:
# awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd root /bin/bash bash /bin/bash testbash /bin/bash basher /bin/bash 0000 /bin/bash
邏輯操做符:
&&:與
||:或
!:非
函數調用:
function_name(argu1, argu2, ...)
條件表達式:
selector?if-true-expression:if-false-expression
說明:若是selector爲真,則執行if-true-expression,不然執行if-false-expression
Example:
# awk -F: '{$3>=1000?userType="Common User":userType="Sysadmin or SysUser"; printf "%15s: %-s\n",$1,userType}' /etc/passwd //根據UID判斷用戶的類型 root: Sysadmin or SysUser bin: Sysadmin or SysUser daemon: Sysadmin or SysUser adm: Sysadmin or SysUser lp: Sysadmin or SysUser sync: Sysadmin or SysUser shutdown: Sysadmin or SysUser halt: Sysadmin or SysUser mail: Sysadmin or SysUser operator: Sysadmin or SysUser
五、PATTERN,
功能:對行進行選擇,即地址定界
(1) empty:空模式,匹配每一行;
(2) /regular expression/:僅處理可以被此處的模式(正則表達式)匹配到的行;
Example: 打印/etc/fstab文件中,以UUID開頭行的第一個字段:
# awk '/^UUID/{print $1}' /etc/fstab UUID=d6ac1399-a5b3-4c3c-8d36-6c720d57d398 UUID=82f438e5-4b76-4f0f-97df-74996cc8c97d UUID=d6ac1399-a5b3-4c3c-8d36-6c720d57d398 UUID=f6cb4dd7-7b40-427a-8808-1a957566ce54
(3) relational expression: 關係表達式;結果有「真」有「假」;結果爲「真」纔會被處理;
真:結果爲非0值,非空字符串;
Example: 打印UID大於等於1000的用戶:
# awk -F: -v OFS='-->' '$3>=1000{print $1,$3}' /etc/passwd nfsnobody-->65534 vuser-->1000 tom-->1001 jerry-->1002
(4) line ranges:行範圍
startline,endline:/pat1/,/pat2/
注意: 不支持直接給出數字的格式
Example: 打印/etc/passwd文件中第10行到第20行之間的用戶名:
# nl /etc/passwd | awk -F: '(NR>=10 && NR<=20){print $1}' 10 operator 11 games 12 ftp 13 nobody 14 dbus 15 polkitd 16 avahi 17 avahi-autoipd 18 postfix 19 sshd 20 systemd-bus-proxy
(5) BEGIN/END模式
BEGIN{}: 僅在開始處理文件中的文本以前執行一次;如打印表頭
END{}:僅在文本處理完成以後執行一次;如打印表尾
Example:
以表格方式打印UID大於1000的用戶名:
$ awk -v FS=':' 'BEGIN{print " Username UID \n========================"} $3>=1000{printf "%10s\t%s\n",$1,$3} END{print "========================\nEND"}' /etc/passwd Username UID ======================== nobody 65534 yinkai 1000 ======================== END
六、經常使用的action
(1) Expressions,表達式;如A>B, B=6等
(2) Control statements,控制語句;如if, while等;
(3) Compound statements:組合語句;一個以上的語句需使用{}括起來
(4) input statements: 輸入語句;
(5) output statements: 輸出語句,如: print。
七、控制語句
if(condition) {statments} //statments語句中若是隻有一條語句花括號能夠省略
if(condition) {statments} else {statements}
while(conditon) {statments}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array[index]
delete array
exit
{ statements }
Example:
7.1 if-else
語法:if(condition) statement [else statement]
使用場景:對awk取得的整行或某個字段作條件判斷;
Example:
打印UID大於1000的用戶名和UID:
$ awk -F: '{if($3>=1000) print $1,$3}' /etc/passwd nobody 65534 yinkai 1000
當用戶的UID大於1000時打印用戶爲Common User,不然打印用戶爲Sysadmin or Sysuser:
~]# awk -F: '{if($3>=1000) {printf "Common User:%s\n",$1} else{printf "Sysadmin or Sysuser: %s\n",$1}}' /etc/passwd root or Sysuser: usbmux Common User: yinkai root or Sysuser: mysql
打印默認shell爲bash的用戶名:
~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
or
$ awk -F: '{if($NF~/bash$/) print $1}' /etc/passwd root yinkai
打印行字段大於5的行:
~]# awk '{if(NF>5) print $0}' /etc/fstab # /etc/fstab: static file system information. # Use 'blkid' to print the universally unique identifier for a
打印空間佔用超過%20的磁盤:
~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
or
~]# df -Th | awk -F% '/^\/dev/{print $1}'| awk '{if($NF>=20) print $1,"------------->",$NF"%"}' /dev/sdb3 -------------> 54% /dev/sdb3 -------------> 54% /dev/sda2 -------------> 37% /dev/sda1 -------------> 76% /dev/sda3 -------------> 84%
7.2 while循環
語法:while(condition) statement
條件「真」,進入循環;條件「假」,退出循環;
使用場景:對一行內的多個字段逐一相似處理時使用;對數組中的各元素逐一處理時使用;
Example:
打印/etc/grub2.cfg文件中以linux16的行(前能夠有空格)中各字段的內容及字段字箱的個數(使用length()函數統計字符個數):
~]# awk '/^[[:space:]]*linux16/{i=1; while(i<=NF) {printf "%50s: %i\n", $i,length($i); i++}}' /etc/grub2.cfg
打印/etc/grub2.cfg文件中以linux16的行(前能夠有空格)中字段字符大於等於7的內容及字段字符個數(使用length()函數統計字符個數):
~]# awk '/^[[:space:]]*linux16/{i=1; while(i<=NF) {if(length($i)>=7) {printf "%50s: %i\n", $i,length($i)}; i++}}' /etc/grub2.cfg
7.3 do-while循環
語法:do statement while(condition)
意義:至少執行一次循環體
7.4 for循環
語法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
特殊用法:
可以遍歷數組中的元素;
語法:for(var in array) {for-body}
Example:
打印/etc/grub2.cfg文件中以linux16的行(前能夠有空格)中字段字符大於等於7的內容及字段字符個數(使用length()函數統計字符個數):
~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {if(length($i)>=7) {printf "%50s: %i\n", $i,length($i)}}}' /etc/grub2.cfg
7.5 switch語句
語法:switch(expression) {case VALUE1 or /REGEXP1/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
說明:expression是一個表達式,若是該表達式的值符合第一個值(VALUE1)或能被第一個正則表達式(REGEXP1)匹配到就執行第一個case的statement,其餘分支就再也不判斷。不然,再逐一去匹配第二個case,此處的case是關鍵字。
7.6 break和continue
break [n] : 退出n層循環;
continue:退出本次循環;
7.7 next
功能:控制awk的內生行循環,提早結束對本行的處理而直接進入下一行;
Example:
打印UID爲偶數的用戶的用戶名:
~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
or
# awk -F: '{if($3%2==0) print $1,$3}' /etc/passwd
八、array
索引數組:awk索引數組的下標從1開始標號;
關聯數組:array[index-expression]
index-expression:
(1) 可以使用任意字符串;字符串要使用雙引號;
(2) 若是某數組元素事先不存在,在引用時,awk會自動建立此元素,並將其值初始化爲「空串」;
若要判斷數組中是否存在某元素,要使用"index in array"格式進行;
weekdays["mon"]="Monday"
Example:
# awk 'BEGIN{weekday["mon"]="Monday"; weekday["tue"]="Tuesday"; print weekday["mon"]}' Monday # awk 'BEGIN{weekday["mon"]="Monday"; weekday["tue"]="Tuesday"; print weekday["tue"]}' Tuesday
若要遍歷數組中的每一個元素,要使用for循環;
for(var in array) {for-body}
注意:var會遍歷array的每一個索引;
如用awk打印tcp鏈接狀態的時候,在第一次引用一個狀態的時候會建立一個以該狀態爲索引的數組,初始值爲0,自增後爲1,每需到一個相同的索引其值再自增1,如:
state["LISTEN"]++
state["ESTABLISHED"]++
Example:
逐一遍歷數組中每一個元素並打印:
~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}' Tuesday Monday
統計tcp各狀態的會話數:
~]# netstat -tan | awk '/^tcp\>/{state[$NF]++} END{for(i in state) {print i": "state[i]}}' LISTEN: 2 ESTABLISHED: 5
統計/var/log/httpd/access_log中每一個IP請求的次數:
~]# awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
練習1:統計/etc/fstab文件中每一個文件系統類型出現的次數;
~]# awk '/^[^#]/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
練習2:統計指定文件中每一個單詞出現的次數;
~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
九、函數
9.1 內置函數
數值處理:
rand():返回0和1之間一個隨機數;
Example:
# awk 'BEGIN{print rand()}' 0.237788
字符串處理:
length([s]):返回指定字符串的長度;
sub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,並將其第一次出現替換爲s所表示的內容;如:sub(a,A,abc)表示在abc中查找a,並替換成A,結果爲Abc
gsub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,並將其全部出現均替換爲s所表示的內容;
split(s,a[,r]):以r爲分隔符切割字符s,並將切割後的結果保存至a所表示的數組中;
Example: 統計TCP會話中各IP的鏈接數:
~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
9.2 自定義函數