一,什麼是awk
awk是linux下的一個命令,他對其他命令的輸出,對檔案的處理都十分強大,其實他更像一門程式設計語言,他可以自訂變數,有條件陳述式,有迴圈,有數組,有正則,有函數等。他讀取輸出,或者檔案的方式是一行,一行的讀,根據你給出的條件進行尋找,並在找出來的行中進行操作,感覺他的設計思想,真的很簡單,但是結合實際情況,具體操作起來就沒有那麼簡單了。他有三種形勢,awk,gawk,nawk,平時所說的awk其實就是gawk。
二,awk中的記錄,域,分割符
當我們讀取輸出時,或者讀取檔案時,讀取一行就是一個記錄。記錄分割符是預設是斷行符號符,儲存在RS,ORS中。
我們從屬記錄中分割出我們要單詞,或者是片語等,我們稱他為域,域分割符,預設的是空格和TAB銉,儲存在內建變
量ORS中。舉個例子:
aaaa:bbbb:ccccccc
1111:2343:5t43343
上面有二行,這二行就是二個記錄,每行後面的斷行符號呢,就是記錄分割符,裡面冒號呢,就是域分割符,分割出來的,aaaa,1111這類東西就是域了。
awk -F: '{print $1}' testfile
三,awk的內建變數和運算子
1,變數
變 量 |
描述 |
$n |
目前記錄的第n個欄位,欄位間由 FS分隔。 |
$0 |
完整的輸入記錄。 |
ARGC |
命 令行參數的數目。 |
ARGIND |
命令列中當前檔案的位置(從0開始算)。 |
ARGV |
包 含命令列參數的數組。 |
CONVFMT |
數字轉換格式(預設值為%.6g) |
ENVIRON |
環 境變數關聯陣列。 |
ERRNO |
最後一個系統錯誤的描述。 |
FIELDWIDTHS |
字 段寬度列表(用空格鍵分隔)。 |
FILENAME |
當前檔案名稱。 |
FNR |
同 NR,但相對於當前檔案。 |
FS |
欄位分隔符號(預設是任何空格)。 |
IGNORECASE |
如 果為真,則進行忽略大小寫匹配。 |
NF |
目前記錄中的欄位數。 |
NR |
當 前記錄數。 |
OFMT |
數位輸出格式(預設值是%.6g)。 |
OFS |
輸 出欄位分隔符號(預設值是一個空格)。 |
ORS |
輸出記錄分隔字元(預設值是一個分行符號)。 |
RLENGTH |
由 match函數所匹配的字串的長度。 |
RS |
記錄分隔字元(預設是一個分行符號)。 |
RSTART |
由 match函數所匹配的字串的第一個位置。 |
SUBSEP |
數組下標分隔字元(預設值是\034)。 |
2,運算子
運算子 |
描述 |
= += -= *= /= %= ^= **= |
賦值 |
?: |
C條件運算式 |
|| |
邏 輯或 |
&& |
邏輯與 |
~ ~! |
匹 配Regex和不匹配Regex |
< <= > >= != == |
關 系運算子 |
空格 |
串連 |
+ - |
加,減 |
* / & |
乘,除與求餘 |
+ - ! |
一元加,減和邏輯非 |
^ *** |
求冪 |
++ -- |
增加或減少,作為首碼或尾碼 |
$ |
字 段引用 |
in |
數群組成員 |
四,awk的正則
匹配符 |
描述 |
\Y |
匹配一個單詞開頭或者末尾的Null 字元串 |
\B |
匹配單詞內的Null 字元串 |
\< |
匹配一個單詞的開頭的Null 字元串,錨定開始 |
\> |
匹配一個單詞的末尾的Null 字元串,錨定末尾 |
\W |
匹配一個非字母數字組成的單詞 |
\w |
匹配一個字母數字組成的單詞 |
\' |
匹配字串末尾的一個Null 字元串 |
\‘ |
匹配字串開頭的一個Null 字元串 |
五,awk的函數
1,字串函數
函數名 |
描述 |
sub |
匹配記錄中最大、最靠左邊的子字串的Regex,並用替換字串替換這些字串。如果沒有指定目標字串就預設使用整個記錄。替換隻發生在第一次匹配的 時候 |
gsub |
整個文檔中進行匹配 |
index |
返回子字串第一次被匹配的位置,位移量從位置1開始 |
substr |
返回從位置1開始的子字串,如果指定長度超過實際長度,就返回整個字串 |
split |
可按給定的分隔字元把字串分割為一個數組。如果分隔字元沒提供,則按當前FS值進行分割 |
length |
返回記錄的字元數 |
match |
返回在字串中Regex位置的索引,如果找不到指定的Regex則返回0。match函數會設定內建變數RSTART為字串中子字串的開始位 置,RLENGTH為到子字串末尾的字元個數。substr可利於這些變數來截取字串 |
toupper和tolower |
可用於字串大小間的轉換,該功能只在gawk中有效 |
2,數學函數
函數名 |
傳回值 |
atan2(x,y) |
y,x 範圍內的餘切 |
cos(x) |
餘弦函數 |
exp(x) |
求 冪 |
int(x) |
取整 |
log(x) |
自然對 數 |
rand() |
隨機數 |
sin(x) |
正弦 |
sqrt(x) |
平 方根 |
srand(x) |
x是rand()函數的種子 |
int(x) |
取 整,過程沒有舍入 |
rand() |
產生一個大於等於0而小於1的隨機數 |
六,執行個體
學習awk的時候,做了一個例子,學東西,不要光看,光看是記不住東西的。光看的話,也許你知道怎麼回事,真正實際操作,不是這兒有問題,就是那兒有問題。所以一定要動手親自操作一下。
1,測試檔案test
複製代碼 代碼如下:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
mail:x:8:12:mail:/var/spool/mail:/bin/false
ftp:x:14:11:ftp:/home/ftp:/bin/false
&nobody:$:99:99:nobody:/:/bin/false
zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash
http:x:33:33::/srv/http:/bin/false
dbus:x:81:81:System message bus:/:/bin/false
hal:x:82:82:HAL daemon:/:/bin/false
mysql:x:89:89::/var/lib/mysql:/bin/false
aaa:x:1001:1001::/home/aaa:/bin/bash
ba:x:1002:1002::/home/zhangy:/bin/bash
test:x:1003:1003::/home/test:/bin/bash
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
例1:
複製代碼 代碼如下:
cat test | awk -F: '{\
if ($1 == "root"){\
print $1;\
}else if($1 == "bin"){\
print $2;\
}else{\
print $3;\
} \
}'
例2:
複製代碼 代碼如下:
awk '{\
for(i=0;i<NF;i++){\
if ($i ~/^root/){\
print $i;\
}else if($i ~/zhangy/){\
print $i;continue;\
}else if($i ~/mysql/){\
print $i;next;\
}else if($i ~/^test/){\
print $i;break;\
} \
}\
}' test
例3:
複製代碼 代碼如下:
tail test | awk 'BEGIN{while(getline d){ split(d,test);for(i in test){\
print test[i]\
}}}'
例4:
複製代碼 代碼如下:
ls -al /home/zhangy/mytest | awk 'BEGIN{while(getline d){ split(d,test);\
print test[9] ;}
}'
例5:
複製代碼 代碼如下:
echo "32:34" |awk -F: '{print "max = ",max($1,$2)}\
function max(one,two){
if(one > two){
return one;
}else{
return two;
}
}
'
例6:
複製代碼 代碼如下:
#awk 'BEGIN{print "what is your name"; getline name < "/dev/tty"}$1 ~name{print
#"found name on line" NR}END{print "see you" name}' test
#awk '{sub(/daemon/,"tankzhang");print}' test
#awk '{{sub(/zhangy/,"tankzhang");$1};print}' test
#awk '{{gsub(/zhangy/,"tankzhang");$1};print}' test
#awk -F: '{print index("zhangy",$1)}' test
#awk -F: '{print substr($1,1,2)}' test
awk -F: '{mat=match($1,/^[a-zA-Z]+$/);print mat,RSTART,RLENGTH}' test
例7:
複製代碼 代碼如下:
cat test |awk -F: '\
NF != 7{\
printf("line %d,does not have 7 fields:%s\n",NR,$0)}\
$1 !~ /^[A-Za-z0-9]/{printf("line %d,non alpha and numeric user id:%s: %s\n",NR,$1,$0)}\
$2 == "*" {printf("lind %d,no password:%s\n",NR,$0)}'