溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

awk命令用法及編程

發(fā)布時(shí)間:2020-06-26 16:27:22 來(lái)源:網(wǎng)絡(luò) 閱讀:766 作者:weilovepan520 欄目:網(wǎng)絡(luò)安全

awk(gawk):報(bào)告生成器,格式化文本輸出:awk,gawk

基本用法:gawk [options] program FILE ...

    program: PATTERN{ACTION STATEMENT};可以有多個(gè),語(yǔ)句之間用分號(hào)分隔

print,printf

選項(xiàng): 

    -F:指明輸入數(shù)據(jù)時(shí)用到的字段分隔符

    -v var=value:自定義變量;


變量:

    1)內(nèi)建變量

        FS:input field seperator(輸入字段分隔符,默認(rèn)為空白字符)

            #awk -v FS=':' '{print $1}' /etc/passwd

            #awk -F: ‘{print $1}’ /etc/passwd(這個(gè)命令和上面的命令效果是一樣的)

        注:使用FS可以一次使用多個(gè)字符做為分隔符;例:awk -v FS="[,:]" '{print $3,$1,$2}' d.txt

        OFS:output field seperator(輸出字段分隔符,默認(rèn)為空白字符)

            #awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd

        RS:input record seperator,輸入時(shí)的換行符;

        ORS:output record seperator,輸出時(shí)的換行符;

        NF:number of field,每一行字段數(shù)量

            {print NF},{print $NF}(在awk中引用變量不需要加$符號(hào))

            一行中的最后一個(gè)字段用$NF表示

        NR:number of record,處理過(guò)的行數(shù)

            #awk ‘{print NR}’ /etc/fstab

        FNR:每一個(gè)文件處理過(guò)的行數(shù)

            #awk ‘{print FNR}’ /etc/fstab /etc/issue

        FILENAME:當(dāng)前正在處理的文件的文件名

            #awk ‘{print FILENAME}’ /etc/fstab

        ARGC:命令行參數(shù)的個(gè)數(shù)

            #awk 'BEGIN{print ARGC}' /etc/fstab

        ARGV:數(shù)組,保存的是命令行所給定的各參數(shù)

            #awk 'BEGIN{print ARGV[0]}' /etc/fstab

    2)自定義變量

        -v var=value

        變量名區(qū)分字符大小寫(xiě);

        #awk -v test='Hello gawk' 'BEGIN{print test}'

        在program中直接定義

        #awk 'BEGIN{test="Hello gawk";print test}'

操作符: 

    算術(shù)運(yùn)算操作符:

        x+y,x-y,x*y,x/y,x^y(次方),x%y

        -x

        +x:轉(zhuǎn)換為數(shù)值

        字符串操作符:默認(rèn)為沒(méi)有符號(hào)的操作符:表示字符串連接

        賦值操作符:

            =,+=,-=,*=,/=,%=,^=

        比較操作符:

            >,>=,<,<=,!=,==

        模式匹配符:

            ~:是否匹配

            !~:是否不匹配

        邏輯操作符:

            &&:與

            ||:或

            ?。悍?/p>

        函數(shù)調(diào)用:

            function_name(argu1,argu2,...)

        條件表達(dá)式:

            selector?if-true-expression:if-false-expression

            #awk-F: '{$3>=1000?usertype="Common User":usertype="SysadminUser";printf                    "%15s:%-s\n",$1,usertype}' /etc/passwd

printf格式化輸出:

    格式化輸出的命令:printf FORMAT,item1,item2,...

        (1)FORMAT必須要給出

        (2)Printf不會(huì)自動(dòng)換行,如果需要換行,需要顯式給出換行控制符,\n

        (3)FORMAT中需要分別為后面的每個(gè)item指定一個(gè)格式化符號(hào)

    格式符:

        %c:顯示字符的ASCII碼;

        %d,%i:顯示十進(jìn)制整數(shù);

        %e,%E:科學(xué)計(jì)數(shù)法計(jì)數(shù)顯示

        %f:顯示為浮點(diǎn)數(shù);

        %g,%G:以科學(xué)計(jì)數(shù)法或浮點(diǎn)形式顯示數(shù)值;

        %s:顯示字符串;

        %u:無(wú)符號(hào)整數(shù);

        %%:顯示%自身;

    修飾符:

        #[.#]:第一個(gè)數(shù)字用來(lái)控制顯示的寬度:第二個(gè)#表示小數(shù)點(diǎn)后的精度,可以省略

            #awk -F: '{printf "Username:%20s UID:%d\n",$1,$3}' /etc/passwd

        -:左對(duì)齊

            #awk -F: '{printf "Username:%-20s UID:%d\n",$1,$3}' /etc/passwd

        +:顯示數(shù)值的符號(hào),負(fù)數(shù)顯示為-,正數(shù)顯示為+號(hào)

            #awk -F: '{printf "Username:%20s UID:%+d\n",$1,$3}' /etc/passwd

模式匹配:

    1)empty:空模式,匹配每一行;

    2)/regular expression/:僅處理能夠被此處的模式匹配到的行

            #awk '/^#/{print}' /etc/fstab

            #awk '!/^#/{print}' /etc/fstab

    3)relational expression:關(guān)系表達(dá)式,結(jié)果有”真“有“假”:結(jié)果為”真“才會(huì)被處理:真:結(jié)果為非0值,非空字符串;

        #awk -F: '$3>=1000{print $1,$3}' /etc/passwd

        #awk -F: '$3<=1000{print $1,$3}' /etc/passwd

        #awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd

        #awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd

    4)line ranges:地址定界(行范圍)

        #awk -F: '/^root/,/^liu/{print $1}' /etc/passwd

        注意:不支持直接給出數(shù)字的格式

        #awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd

    5)BEGIN/END模式

        BEGIN{}:表示僅在開(kāi)始處理文件中每一行文本之前執(zhí)行一次的程序;

        END{};表示僅在文本處理完成之后,命令結(jié)束之前執(zhí)行一次的程序;

條件判斷,循環(huán):

    條件判斷:

        if(condition){statements} 

       例:#awk -F: '{if($3>=1000) print $1,$3}' /etc/passwd 

if(confition){statements} else {statements}

        例:#awk -F: '{if($3>=1000) {printf "Commono user:%s\n",$1} else {printf "root orSysuser:%s\n",$1}}' /etc/passwd

    循環(huán):

while(condition) {statements}:條件為“真”,進(jìn)入循環(huán):條件為“假”,退出循環(huán)

例:#awk -v i=1 'BEGIN{while(i<=4){print i;++i}}'

for(expr1;expr2;expr3) {statements}

例:#awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' grub2.cfg 

        for(var in array) {for-body}:常用于遍歷數(shù)組中的元素

        例:#netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) {print i,state[i]}}'

#awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /usr/logcal/nginx/logs/access.log

    跳出循環(huán):

       break:跟出整個(gè)循環(huán)

       continue:跳出當(dāng)前循環(huán),進(jìn)入下一個(gè)循環(huán)

       next:提前結(jié)束對(duì)本行的處理,直接進(jìn)入下一行

       例:#awk -F: '{if($3%2!=0) next;print $1,$3}' /etc/passwd

數(shù)組:

    關(guān)聯(lián)數(shù)組是awk一個(gè)獨(dú)特的特征,它的一個(gè)強(qiáng)大的功能就是可以使用字符串作為一個(gè)數(shù)據(jù)的下標(biāo)

    Index-erpression:

        若某數(shù)組事先不存在,則在使用時(shí)直接創(chuàng)建,并將其初始化為空的數(shù)組;

        可使用任意字符串作為下標(biāo);字符串要使用雙引號(hào);

        若要判斷數(shù)組中是否存在某元素,要使用”index in array“格式進(jìn)行:

    若要遍歷數(shù)組中的每個(gè)元素,要使用for循環(huán);

         for(var in array) {for-body}

        注意:var會(huì)遍歷array的每個(gè)索引;

     刪除數(shù)組中的元:

        delete array[subscript]

函數(shù):

    awk的內(nèi)置函數(shù)可以分為兩組:算術(shù)函數(shù)和字符串函數(shù)

    1)內(nèi)置函數(shù)

        數(shù)值處理:

            rand():返回0和1之間一個(gè)隨機(jī)數(shù);

        字符串處理;

            length([s]):返回指定字符串的長(zhǎng)度

            sub(r,s,[t]):以r表示的模式來(lái)查找t所表示的字符中的匹配的內(nèi)容,并將其第一次出現(xiàn)替換為s所表示的內(nèi)容;

            gub(r,s,[t]):以r表示的模式來(lái)查找t所表示的字符中的匹配的內(nèi)容,并將其全部替換為s所表示的內(nèi)容;

            split(s,a[,r]):以r為分隔符切割字符s,并將切割后的結(jié)果保存至a所表示的數(shù)組中;

              #netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'

           getline函數(shù):

               getline函數(shù)的作用是從文本中讀取內(nèi)容,也可以從管道中接收內(nèi)容

               getline函數(shù)的用法比較特殊,不能使用getline(),它的語(yǔ)法不允許有圓括號(hào),只能使用getline

               從文件中讀取內(nèi)容:getline < "a"  --> 從文件a中讀取內(nèi)容,小于號(hào)表示重定向,不能理解為小于號(hào)

               將讀取的內(nèi)容賦給一個(gè)變量:getline name < "a"

    2)自定義函數(shù)

練習(xí):

    1.統(tǒng)計(jì)/etc/fstab文件中每個(gè)文件系統(tǒng)類型出現(xiàn)的次數(shù);

    2.統(tǒng)計(jì)指定文件中每個(gè)單詞出現(xiàn)的次數(shù);

    3.統(tǒng)計(jì)下面語(yǔ)句中,每個(gè)單詞及字符出現(xiàn)的個(gè)數(shù)

        the squid project provides a number of resources toassist users design,

        implement and support squid installations. Please browsethe documentation 

        and support ections for more infomation

    4.統(tǒng)計(jì)grade.txt中的分?jǐn)?shù)的平均數(shù)     

        mona 70 77 85 83 70 89

        john 85 92 78 94 88 91

        andrea 89 90 85 94 90 95

        jasper 84 88 80 92 84 82

        dunce 64 80 60 60 61 62

        ellis 90 98 89 96 96 92

    5.在問(wèn)題4的基礎(chǔ)上統(tǒng)計(jì)grade.txt中班級(jí)平均分?jǐn)?shù),并以A,B,C,D為同學(xué)平均分做出分類并統(tǒng)計(jì)?

    6.文件test中有如下內(nèi)容:

       zhangsan     80

       lisi         81.5

       wangwu       93

       zhangsan     85

       lisi         88

       wangwu       97

       zhangsan     90

       lisi         92

       wangwu       88

       要求輸出格式:(average:平均成績(jī),total:總成績(jī)) 

       name#######average#######total 

       zhangsan   xxx            xxx 

       lisi       xxx            xxx 

       wangwu     xxx            xxx

答案:

1.

#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

3.

統(tǒng)計(jì)字符出現(xiàn)的次數(shù)

#grep -o "\w" c.txt | awk '{s[$1]++}END{for (key in s) print key,s[key]}'

統(tǒng)計(jì)單詞出現(xiàn)的次數(shù)

#awk 'BEGIN{RS="[ .,]+"}{words[$1]++}END{for(i in words){print i,words[i]}}' c.txt

4.

[root@localhost ~]# cat 8.awk 
{
total=0
for(i=2;i<=NF;i++){
total += $i
avg=total/(NF-1)
}
print NR,$1,avg
}

5.

[root@localhost ~]# cat grades.awk 
BEGIN{OFS="\t"}
{
total=0
for(i=2;i<=NF;i++){
total += $i
avg=total/(NF-1)
}
student_avg[NR]=avg
if(avg>=90) grade="A"
else if(avg>=80) grade="B"
else if(avg>=70) grade="C"
else if(avg>=60) grade="D"
else grade="F"
++class_grade[grade]
}
END{
for(x=1;x<=NR;x++){
	class_avg_total += student_avg[x]
	print student_avg[x]
}
class_average=class_avg_total/NR
for(x=1;x<=NR;x++){
	if(student_avg[x]>=class_average)
		++above_average
	else
		++below_average
}
print ""
print "班級(jí)平均分?jǐn)?shù):",class_average
print "大于平均分?jǐn)?shù)有:"above_average" 位同學(xué)!"
print "低于平均分?jǐn)?shù)有:"below_average" 位同學(xué)!"
for(letter_grade in class_grade){
	print letter_grade":" class_grade[letter_grade] | "sort"
}
}

6.

[root@localhost ~]# awk 'BEGIN{print "name\taverage\ttotal"}{a[$1]+=$2;b[$1]++}END{for(i in a){print i"\t"a[i]/b[i]"\t"a[i]}}' test
name	average	total
zhangsan	85	255
wangwu	92.6667	278
lisi	87.1667	261.5
解析:
    a[$1]+=$2:把第一列作為數(shù)組的下標(biāo),累計(jì)相加的結(jié)果作為對(duì)應(yīng)數(shù)組的元素(即值)
    b[$1]++:把第一列作為數(shù)組的下標(biāo),每出現(xiàn)一次計(jì)數(shù)器加1并且作為數(shù)組的元素(即值)



向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI