一、文本處理工具
grep、sed和awk都是文本處理工具,雖然都是文本處理工具但卻都有各自的優缺點,一種文本處理命令是不能被另一個完全替換的,否則也不會出現三個文本處理命令了。只不過,相比較而言,sed和awk功能更強大而已,且已獨立成一種語言來介紹。
grep:文本過濾器,如果僅僅是過濾文本,可使用grep,其效率要比其他的高很多; sed:Stream EDitor,流編輯器,默認只處理模式空間,不處理原數據,如果你處理的數據是針對行進行處理的,可以使用sed;awk:報告生成器,格式化以後顯示。如果對處理的數據需要生成報告之類的信息,或者你處理的數據是按列進行處理的,最好使用awk。
二、awk可以完成的一些功能
將文本文件看做由記錄和字段組成的文本數據庫
使用變量操作數據庫
使用算術和字符串操作符
使用普通的程序設計結構,例如循環和條件
生幫格式化報告
定義函數
從腳本中執行unix命令
處理unix命令的結果
更加巧妙的處理命令行的參數
更容易地處理多個輸入流
三、語法格式
1 2# awk [options] 'script' file1 file2, ...
# awk [options] 'PATTERN { action }' file1 file2, ..
1、選項
-F fs or --field-separator fs:
指定輸入文件折分隔符,fs是一個字符串或者是一個正則表達式,如-F:
1 2 3 4#awk -F: '/root/{print $1,$NF}' /etc/passwd
#awk -F: '/root/{print $1$NF}' /etc/passwd
#awk -F: '/root/{print $1 $NF}' /etc/passwd
#awk -F: '/root/{print $1"#"$NF}' /etc/passwd
-v 選項定義的變量在腳本運行之前即存在,可以在腳本的 BEGIN 流程中被調用;
2、awk的輸出:print和printf
⑴、print的使用格式:
print item1, item2, ...
要點:
①、各項目之間使用逗號隔開,而輸出時則以空白字符分隔;
②、輸出的item可以為字符串或數值、當前記錄的字段(如$1)、變量或awk的表達式;數值會先轉換為字符串,而後再輸出;
③、print命令後面的item可以省略,此時其功能相當於print $0, 因此,如果想輸出空白行,則需要使用print "";
注意,在AWK中,$表示字段,用戶變量不需要加$,這是AWK與shell或者Perl不同之處!在shell中,變量定義時不加$,再次引用時則需要用$,而在Perl中,無論定義和引用時都需要加$ (Perl中$表示標量,另有@和%符號表示數組和Hash變量)。
實例
⑵、printf的使用格式
printf format, item1, item2, ...
format格式的指示符都以%開頭,後跟一個字符,
%c
轉換數字成ASCII,如printf "%c", 67結果為C。
%d, %i
打印十進制整數,如printf "%dn", 6.745結果為6。
%e, %E
轉換數字為科學(指數)符號,如printf "%4.3en", 6745結果為6.745e+03。
%f
以浮點表示法打印數字,如 printf "%4.3f\n", 6745結果為6745.0000000
%s
打印字符串,如printf "%10s\n", 6745結果為十個空格加6745。
可更改的格式:
N$
位置指示符,可調整字符串的輸出位置。printf "%s %s %s\n", "I", "lOVE","YOU"輸出為:I LOVE YOU,我們調整一下位置,printf "%3$s %2$s %1$s\n", "YOU", "LOVE","I",輸出結果為:I LOVE YOU
修飾符
N: 顯示寬度;
-: 左對齊; +:右對齊(也可以顯示數值符號正負之用);3、模式和操作
⑴、模式可以是以下任意一個:
/正則表達式/:使用通配符的擴展集。
關系表達式:可以用下面運算符表中的關系運算符進行操作,可以是字符串或數字的比較,如$2>%1選擇第二個字段比第一個字段長的行。
模式匹配表達式:用運算符~(匹配)和~!(不匹配)。
模式,模式:指定一個行的范圍。該語法不能包括BEGIN和END模式。
BEGIN:讓用戶指定在第一條輸入記錄被處理之前所發生的動作,通常可在這裡設置全局變量。
END:讓用戶在最後一條輸入記錄被讀取之後發生的動作。
⑵、操作由一人或多個命令、函數、表達式組成,之間由換行符或分號隔開,並位於大括號內。主要有四部份:
變量或數組賦值
輸出命令
內置函數
控制流命令
4、變量
⑴、awk內置變量之記錄變量
FS: field separator 讀取文件本時,所使用字段分隔符 RS: Record separator 輸入文本信息所使用的換行符 OFS: Output Filed Separator 輸出字段分隔符(默認值是一個空格) ORS:Output Row Separator 輸出記錄分隔符(默認值是一個換行符)
注:
從$1,$2一直到$NF,整行用$0標,如果$0被賦予新值,所有的$1,$2...和NF都將被重新計算。同樣,若$i被改變,$0將用OFS重新計算。
⑵、awk內置變量之數據變量
NR: The number of input records awk命令所處理的記錄數;如果有多個文件,這個數目會把處理的多個文件中行統一計數 NF:Number of Field 當前記錄的field個數 FNR 當前文件的相對記錄數 ARGV 數組,保存命令行本身這個字符串,如awk '{print $0}' a.txt b.txt這個命令中,ARGV[0]保存awk,ARGV[1]保存a.txt ARGC awk命令的參數的個數 FILENAME awk命令所處理的文件的名稱 ENVIRON 當前shell環境變量及其值的關聯數組
NR用法
NF用法(默認以空格分隔)
FNR用法
ARGV用法
之二
FILENAME用法
ENVIRON用法
注:
ARGV數組由ARGV[0]....ARGV[ARGC-1]組成,第一個元素是0而不是1,這與AWK中的般數組不同
ENVIROND數組在shell與AWK的交互中非常有用,使用ENVIRON["PARA_NAME"]來獲取環境變量$PARA_NAME的值,其中引號“”不可少!
5、標准輸出與重定向
⑴、輸出重定向
print items > output-file print items >> output-file print items | command ⑵、特殊文件描述符: /dev/stdin:標准輸入 /dev/sdtout: 標准輸出 /dev/stderr: 錯誤輸出 /dev/fd/N: 某特定文件描述符,如/dev/stdin就相當於/dev/fd/0;實例:
1 2# awk -F" " '{printf "%-15s %i\n",$1,$3 > "/dev/stderr" }' /etc/issue
# awk -F" " '{printf "%-15s %i\n",$1,$3 > "/dev/null" }' /etc/issue
6、awk的操作符:
⑴、算術操作符: -x: 負值 +x: 轉換為數值; x^y: x**y: 次方 x*y: 乘法 x/y:除法 x+y: x-y:x%y:
實例
⑵、字符串操作符: 只有一個,而且不用寫出來,用於實現字符串連接; ⑶、 賦值操作符: = += -= *= /= %= ^= **= ++ --需要注意的是,如果某模式為=號,此時使用/=/可能會有語法錯誤,應以/[=]/替代;
⑷、布爾值 awk中,任何非0值或非空字符串都為真,反之就為假; ⑸、 比較操作符: x < y True if x is less than y. x <= y True if x is less than or equal to y. x > y True if x is greater than y. x >= y True if x is greater than or equal to y. x == y True if x is equal to y. x != y True if x is not equal to y. x ~ y True if the string x matches the regexp denoted by y. x !~ y True if the string x does not match the regexp denoted by y. subscript in array True if the array array has an element with the subscript subscript. ⑺、表達式間的邏輯關系符: &&||
實例:
⑻、條件表達式: selector?if-true-exp:if-false-exp if selector; then if-true-exp else if-false-exp fi實例
⑼、函數調用:
function_name(para1,para2)7、控制語句
⑴、 if-else語法:
if (condition) {then-body} else {[ else-body ]}
實例:
1 2 3 4#awk '{if ($3==0) {print $1, "Adminitrator";} else { print $1,"Common User"}}' /etc/passwd
#awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd
#awk -F: '{if ($1=="root") printf "%-15s: %s\n", $1,"Admin"; else printf "%-15s: %s\n", $1, "Common User"}' /etc/passwd
#awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
⑵、 while
語法:
while (condition){statement1; statment2; ...}
實例:
1 2 3 4#awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
#awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
#awk '{i=1;while (i<=NF) {if ($i>=20000) print $i; i++}}' random.txt
#random.txt文件的內容為一堆隨機數。
⑶、do-while 至少執行一次循環體,不管條件滿足與否
語法:
do {statement1, statement2, ...} while (condition)
實例:
1 2 3 4 5 6 7 8#awk 'BEGIN{
sum
=0;
i=0;
do
{
sum
+=i;
i++;
}
while
(i<=100)
print
sum
;}'
⑷、for
語法:for ( variable assignment; condition; iteration process) { statement1, statement2, ...}實例:
1#awk -F: '{for(i=1;i<=3;i++) { if (length($i)>=8) {print $i}}}' /etc/passwd
for循環還可以用來遍歷數組元素:
語法:
for (i in array) {statement1, statement2, ...}
實例:
1#awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%-15s:%i\n",A,BASH[A]}}' /etc/passwd
⑸、 case
語法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...} ⑹、 break 和 continue 常用於循環或case語句中 ⑺、 next 提前結束對本行文本的處理,並接著處理下一行;例如,下面的命令將顯示其ID號為奇數的用戶:實例:
1# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
9、awk中使用數組
⑴、 數組 array[index-expression] index-expression可以使用任意字符串;需要注意的是,如果某數據組元素事先不存在,那麼在引用其時,awk會自動創建此元素並初始化為空串;因此,要判斷某數據組中是否存在某元素,需要使用index in array的方式。 要遍歷數組中的每一個元素,需要使用如下的特殊結構:語法
for (var in array) { statement1, ... }
其中,var用於引用數組下標,而不是元素值; 實例: 1#netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
⑵、 刪除數組變量
從關系數組中刪除數組索引需要使用delete命令。使用格式為:
delete array[index]
10、awk的內置函數
split(string, array [, fieldsep [, seps ] ])
功能:將string表示的字符串以fieldsep為分隔符進行分隔,並將分隔後的結果保存至array為名的數組中;數組下標為從1開始的序列;
實例:
1
2
3
# netstat -ant | awk '/:80\>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}' | sort -rn | head -50
# netstat -tan | awk '/:80\>/{split($5,clients,":");ip[clients[4]]++}END{for(a in ip) print ip[a],a}' | sort -rn | head -50
# df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]>=20){print $1}}'
length([string])
功能:返回string字符串中字符的個數; substr(string, start [, length])功能:取string字符串中的子串,從start開始,取length個;start從1開始計數;
1# tail -10 /etc/passwd |awk -F: '{print substr($1,1,6)}'
system(command)
功能:執行系統command並將結果返回至awk命令
1# awk 'BEGIN{print system("ls -l")}'
systime()
功能:systime函數返回從1970年1月1日開始到當前時間(不計閏年)的整秒數
tolower(s) 功能:將s中的所有字母轉為小寫 toupper(s) 功能:將s中的所有字母轉為大寫 1# awk 'BEGIN{s="acl";print toupper(s)}'
================================完===================================================
PS:
awk簡單應用到此結束!
AWK簡介及使用實例 http://www.linuxidc.com/Linux/2013-12/93519.htm
AWK 簡介和例子 http://www.linuxidc.com/Linux/2012-12/75441.htm
Shell腳本之AWK文本編輯器語法 http://www.linuxidc.com/Linux/2013-11/92787.htm
正則表達式中AWK的學習和使用 http://www.linuxidc.com/Linux/2013-10/91892.htm
文本數據處理之AWK 圖解 http://www.linuxidc.com/Linux/2013-09/89589.htm
如何在Linux中使用awk命令 http://www.linuxidc.com/Linux/2014-10/107542.htm
文本分析工具-awk http://www.linuxidc.com/Linux/2014-12/110939.htm