1、awk介紹
awk(名字來源於三個創始人姓氏首字母)是linux系統下文本編輯工具,是一門編程語言,有本身的基本語法和流程控制、函數。awk簡單高效。
2、awk的運行方法
例子:使用冒號:分割/etc/passwd,打印出第一列
1.經過命令行執行
awk -F: '{print $1}' /etc/passwd
2.經過執行awk文件來執行
awk文件的格式:
#!/usr/bin/awk
BEGIN{ FS=":"}
{print $1}
而後調用這個awk文件的格式:awk -f awk腳本文件 /etc/passwd
3、awk的基本語法
awk經過FS做爲每一段文本的分割符(默認空格),在命令行上能夠用-F參數指定分隔符;
經過RS參數指定文本換行符(默認回車,因此是一行行取數據的),經過換行符做爲分割來讀取文件。這裏區別於sed,sed是一行一行讀取文件的
基本流程:
BEGIN{在讀取文件以前作的操做}
{讀取文件時作的操做}
END{所有文件讀取以後才進行的操做}
經常使用內置變量:
$0 當前全部字段
$1--$n 按照分隔符分割取到的第n列內容
FS 分隔符(默認空格) awk 'BEGIN{FS=":"}{print $1}' /etc/passwd ;等價於awk -F: '{print $1}' /etc/passwd
RS 換行符(默認回車) awk 'BEGIN{RS=":"}{print $1}' /etc/passwd
NF 字符列數,當前處理行的分割後的列數 awk -F: '{print NF}' /etc/passwd
NR 行號 awk -F: '{print NR ":" $1}' /etc/passwd
OFS (默認空格)輸出字段分隔符
ORS (默認回車)輸出記錄分隔符
自定義外部變量:
-v:自定義變量
awk -v host=$HOSTNAME "BEGIN{print host}"
關係操做符:<、>、<=、>=、==、!=、~、!~
比較符<等與其餘的語言相似,重點說一下不同的
~:用來判斷前面的列是否匹配後面的內容。例如awk -F: '$7 ~ /^\/bin/{print $0}' /etc/passwd(判斷第7列是否以/bin開頭,若是是打印該列)
!~:不匹配
輸出:print與printf
print:直接輸出 awk -F: '{print $1 ":" $2}' /etc/passwd
printf:格式化輸出(printf是一個函數,須要用到())
awk -F: '{printf(hello %s:%s\n),$1,$2}'
注意:printf須要手動增長\n來換行。使用%s來格式化,printf()外加入要替換的變量
4、awk的流程控制
條件:
if語句 if(expression){action1}else{action2}
例如:產生10個數seq 10,經過if語句判斷是單數仍是雙數
seq 10 |awk '{if($0%2==0){print $0"是雙數"}else{print $0"是單數"}}'
若是隻須要一個if分支,能夠省略前面的if,好比awk -F: '$3<-10 {print $1}' /etc/passwd
循環:
while語句:while(expression){action}
例子:使用:分割/etc/passwd,並將每一列前加上列號
awk -F: '{i=1;while(i<=NF){print i":"$i;i++ }}' /etc/passwd
for語句:
第一種方法:for(i=0;i<=10;i++){action}
例子:使用:分割/etc/passwd,並將每一列前加上列號
awk -F: '{for(i=1;i<=NF;i++){print i":"$i}}' /etc/passwd
第二種方法:for(value in array){action}
當value在array的key中,進行下面的操做。awk的數組相似python中的字典。
例子:統計/etc/passwd第7列的值及對應的個數
awk -F: '{a[$7]++}END{for(i in a)if(i!=""){print i":"a[i]}}' /etc/passwd
說明:a[$7]:將$7做爲數組a的key,而後統計對應的個數;而後遍歷for(i in a),判斷i是否在數組a的key中;若是存在則打印a[i],a[i]爲對應key的值,這裏指個數。
數組:
array[1]="hello"
array["name"]="Jack"
數組相似python的字典,array[key值]="value值";key爲索引,能夠是數字也能夠是字符串。
數組元素的刪除:delete array["key"]
例子:定義了數組a的三個值,並打印結果查看
awk 'BEGIN{a[1]="hello";a[2]="word";a["name"]="meitian";for(i in a){print "key爲"i":value爲"a[i]}}'
5、awk函數
內置函數
1.算術函數:
int(x) 返回x的整數部分的值,值不會四捨五入,只是取整
sqrt(x) 返回x的平方根
rand() 返回僞隨機數r,其中0<=r<1,(僞隨機數指返回的值都是上一次返回的同一個隨機數)
srand(x) 創建rand()新的種子數,若是沒有指定就用當天的時間(使用srand()可使得rand()返回不一樣的隨機數)
例子:rand()產生一個隨機數,經過srand()產生新的種子數,而後再差生一個隨機數
awk 'BEGIN{print rand();srand();print rand()}'
2.字符串函數:
sub("要替換的字符串","替換後的字符串值"):替換匹配到的第一個文本
echo "hello world world" | awk '{sub("world","meitian");print $0}'
gsub("要替換的字符串","替換後的字符串值" ):開啓全局替換,替換文本中全部匹配到的字符串
echo "hello world world" | awk '{gsub("world","meitian");print $0}'
index("a","b"):返回字符串b在字符串a中開始的位置
awk 'BEGIN{print index("hello world","world")}'
length("s"):返回字符串s的長度,當沒有指定s時,返回$0的長度
awk -F 'BEGIN{print length("hello world")}{print lenght()}' /etc/passwd
match("s","r"):若是正則表達式r在s中匹配到,則返回出現的起始位置,不然返回0
awk 'BEGIN{print match("hello world","[wo]")}'
split(s,a,sep) 使用sep將字符串s分解到數組a中,默認sep爲FS。
例子:使用o作爲分隔符,將"hello world"進行分割存儲到數組a中
awk 'BEGIN{print split("hello world",a,"o");for(i in a){print a[i]}}'
toupper(s):將全部小寫字母轉換成大寫字母
echo "hello world" |awk '{print toupper($0)}'
tolower(s):將全部大寫字母轉換成小寫字母
echo "HELLO WORLD" |awk '{print tolower($0)}'
自定義函數:
function 函數名(參數1,參數2,...){語句;return 表達式}
例子:求和
awk 'function sum(a,b){total=a+b;return total}BEGIN{print sum(2,3)}'
注意:函數必須寫在BEGIN{}{}END{}的花括號以外的地方,不能放在任何{}內,不然會報錯`return' used outside function context
6、實戰
1.得到eth0的IP地址
ifconfig eth0 | awk -F":| +" '/inet addr:/{print $4}'
ifconfig eth0的結果:
說明:
1.多個字符做爲分隔符(好比例子中的冒號和空格),可使用|來區分;或者直接使用正則來做區分。好比例子中的-F":| +"能夠寫成-F"[ :]+"
2.若是要過濾多個相同分隔符,可使用正則的+。表示1個或多個
3.awk中可使用'/操做匹配到該內容的行/{匹配到前面的行後進行的操做}'來選擇某些想要的行。好比例子中須要取匹配到「inet addr:」的行,打印第4列,//中的爲正則表達式,若是有/等須要使用\進行轉義
2.統計tcp網絡鏈接數
netstat -an |awk '/^tcp/{a[$NF]++}END{for(i in a){printf("%s:%d\n",i,a[i])}}'
說明:與上面的例子大同小異,/^tcp/表示只處理以tcp開頭的行。$NF表示最後一列
7、在實戰中可能用到的注意點
1.awk須要對文件進行處理。不須要處理文件的能夠把打印命令寫在BEGIN裏(例如:awk -v name=meitian 'BEGIN{print name}')
2.能夠對ls等命令結果進行處理
例子:對包含conf的文件按照.進行分割,並將分割結果用冒號進行鏈接
ls |grep conf |awk -F. '{print $1 ":" $2}'
3.awk使用-v定義變量,可是awk中引用變量時直接使用變量名,不須要在變量前加$
4.將awk中的結果賦值給變量傳遞給shell中用
方法一:可使用eval()函數來將打印的結果轉換成變量。eval會將打印的值當作命令來進行處理,shell中定義變量的格式:變量名=變量值
例子:有個文件名爲search.contract-0.0.5-SNAPSHOT.jar,按照-分割。將-前面的存爲name變量,中間的版本號存爲version變量。
eval $(ls |grep search.contract-0.0.5-SNAPSHOT.jar |awk -F"-" '{printf("name=%s;version=%s\n",$1,$2)}')
方法二:若是隻想保存一個變量,能夠經過變量名=$(操做print變量值)的方法來保存
例如提取ifconfig eth0本機中的IP地址保存到變量a中
a=$(ifconfig eth0 |awk -F":| *" '/inet addr/{print $4}')
5.只對包含某些內容的行進行操做
awk '/要匹配的內容/{進行的操做}' file,//內能夠放入正則表達式,注意對一些特殊字符進行轉義,好比「[]\「
6.awk不能直接修改源文件,能夠經過重導向輸出結果來修改原文件。>(所有覆蓋文件內容)或>>(追加到文件)
awk '/^root/{print $0 >"passwd"}' passwd
注意:重導向輸出的文件名要用雙引號括起來,不然會報錯
7.awk使用雙引號做爲分隔符,可使用單引號括起來,'"'