RHEL6基础三十一之服务器维护基础命令②awk
?格式:awk -F '[分隔符]' '{pattern + action}' filename[s]
工作方式:awk對指定filename[s]逐行掃描,從第一行到最后一行,讀入有'\n'換行符分割的一條記錄,然后將記錄按指定的域分隔符劃分域,每個域部分再進行各種分析處理,尋找匹配的特定模式的行。如果沒有指定處理動作,則把匹配的行顯示到標準輸出(屏幕),如果沒有指定模式,則所有被操作所指定的行都被處理。
說明:awk是一個強大的文本分析工具,用于在linux/unix下對文本和數據進行處理,awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本;模式pattern可以是正則表達式、關系表達式、模式匹配表達式,變量要用' '括起來(awk '$9 ~ /'$pattern'/ {print $6" "$7" "$8}');操作action由一個或多個命令、函數、表達式組成,之間由換行符或分號隔開,
參數:
-F fs:????指定輸入文件折分隔符,FS是一個字符串或者是一個正則表達式,默認是空格或tab,可以同時使用多個域分隔符,這時應該把分隔符寫成放到方括號中,,如$awk -F'[:\t]' '{print $1,$3}' test,表示以空格、冒號和tab作為分隔符。
-v var=value:????????賦值一個用戶定義變量
-f scripfile:????從腳本文件中讀取awk命令
BEGIN:讓用戶指定在第一條輸入記錄被處理之前所發生的動作,通??稍谶@里設置全局變量。
????????BEGIN模塊后緊跟著動作塊,這個動作塊在awk處理任何輸入文件之前執行。所以它可以在沒有任何輸入的情況下進行測試。它通常用來改變內建變量的值,如OFS,RS和FS等,以及打印標題。如:$ awk 'BEGIN{FS=":"; OFS="\t"; ORS="\n\n"}{print $1,$2,$3} test。上式表示,在處理輸入文件以前,域分隔符(FS)被設為冒號,輸出文件分隔符(OFS)被設置為制表符,輸出記錄分隔符(ORS)被設置為兩個換行符。$ awk 'BEGIN{print "TITLE TEST"}只打印標題。
END:讓用戶在最后一條輸入記錄被讀取之后發生的動作
? ? ??END不匹配任何的輸入文件,但是執行動作塊中的所有動作,它在整個輸入文件處理完成后被執行。如$ awk 'END{print "The number of records is" NR}' test,上式將打印所有被處理的記錄數。
print函數的參數可以是變量、數值或者字符串。自定義的內容如字符串、分隔符必須用雙引號引用,逗號如果不用雙引號輸出為空格,輸出域的分隔符默認是一個空格,保存在OFS中。如$ awk -F: '{print $1,$5}' test,$1和$5間的逗號就是OFS的值。
內建變量FS保存輸入域分隔符的值,默認是空格或tab??梢酝ㄟ^-F命令行選項修改FS的值??梢酝瑫r使用多個域分隔符,此時需把分隔符放到方括號中,如$awk -F'[:/t]' '{print $1,$3}' test,表示以空格、冒號和tab作為分隔符
[root@justin?~]#?touch?/home/last [root@justin?~]#?last?-n?5?>?!$ last?-n?5?>?/home/last [root@justin?~]#?cat?/home/last root?????pts/010.15.72.73??????Thu?Nov?21?16:45???still?logged?in reboot???system?boot??2.6.32-279.el6.i?Thu?Nov?21?16:45?-?15:46??(23:01) root?????pts/010.15.72.73??????Mon?Nov?18?11:02?-?down??(1+21:13) reboot???system?boot??2.6.32-279.el6.i?Mon?Nov?18?10:23?-?08:16?(1+21:53) root?????pts/010.15.72.73??????Fri?Nov?15?15:27?-?down???(02:09) wtmp?begins?Wed?Nov?13?17:30:52?2013 [root@justin?~]#?awk?'{print?$3}'?/home/last 10.15.72.73 boot 10.15.72.73 boot 10.15.72.73 Wed [root@justin?~]#?tail?-5?/etc/passwd|awk?-F?':'?'{print?$1}' nfsnobody abrt sshd tcpdump justin [root@justin?~]#?tail?-5?/etc/passwd|awk?-F':'?'{print?$1"\t"$7}' nfsnobody???/sbin/nologin abrt????/sbin/nologin sshd????/sbin/nologin tcpdump?/sbin/nologin justin??/bin/bash [root@justin?~]#
顯示/etc/passwd最后5個賬戶和賬戶對應的shell,而賬戶與shell之間以逗號分割,而且在所有行添加列名name,shell,在最后一行添加"justin1,/bin/nosh"。
[root@justin?~]#?tail?-5?/etc/passwd|awk?-F?:?'BEGIN?{print?"name,shell"}?{print?$1","$7}?END?{print?"justin1,/bin/nosh"}' name,shell nfsnobody,/sbin/nologin abrt,/sbin/nologin sshd,/sbin/nologin tcpdump,/sbin/nologin justin,/bin/bash justin1,/bin/nosh [root@justin?~]#?tail?-5?/etc/passwd|awk?-F?:?'BEGIN?{print?"name,shell"}?{print?$1?,?$7}?END?{print?"justin1,/bin/nosh"}' name,shell nfsnobody?/sbin/nologin abrt?/sbin/nologin sshd?/sbin/nologin tcpdump?/sbin/nologin justin?/bin/bash justin1,/bin/nosh
環境變量:
NF:當前記錄已經瀏覽域的個數,$NF 最后一個域值,$(NF-1)倒數第二個域....
NR:已讀的記錄數,每處理完一條記錄,NR的值就增加1,,$NR 第幾條記錄的域值,NR=3,$NR 第三個域的值
??????? 打印最后一行最后一個域
[root@localhost?platform.wizards]#?ls?-lrt?out-* -rw-r--r--.?1?root?root???70897310?Aug?10?18:00?out-23.log -rw-r--r--.?1?root?root??646081744?Aug?24?05:28?out-37.log -rw-r--r--.?1?root?root?2614436097?Sep?29?05:34?out-38.log -rw-r--r--.?1?root?root????????869?Oct??7?00:09?out-115.log -rw-r--r--.?1?root?root????????902?Oct??7?00:13?out-138.log -rw-r--r--.?1?root?root????????903?Oct??7?00:18?out-161.log -rw-r--r--.?1?root?root??231190061?Oct??8?05:30?out-183.log -rw-r--r--.?1?root?root???79889728?Oct??9?12:13?out-218.log -rw-r--r--.?1?root?root?1364561105?Oct?26?06:09?out-235.log -rw-r--r--.?1?root?root?1505025643?Nov?15?11:14?out-237.log -rw-r--r--.?1?root?root??????29474?Nov?15?17:59?out-239.log -rw-r--r--.?1?root?root??643381486?Nov?23?07:12?out-240.log [root@localhost?platform.wizards]#?ls?-lrt?out-*|awk?'END?{print?$NF}' out-240.log [root@localhost?platform.wizards]#$n:當前行的第n個域,域間由分隔符隔開,$1表示當前行第一個域,$2表示第二個域,$0表示整行記錄;默認情況下各域以空格或tab分隔開
ARGC:????命令行參數的數目。
ARGV?????????????? 命令行參數排列
FILENAME:????當前文件名,awk瀏覽的文件名 ,注意大小寫
FS ? ?字段分隔符(默認是任何空格),等價于命令行 -F選項
OFS??輸出字段分隔符(默認值是一個空格)
ORS????輸出記錄分隔符(默認值是一個換行符)
RS ? ??記錄分隔符(默認是一個換行符)
統計/etc/passwd:文件名,每行的行號,每行的列數,對應的完整行內容:
[root@justin?~]#?awk?-F:?'{print?"filename?:?"?FILENAME,";""linenumber?:?"?NR,";""Total?number?of?columnsis?:"?NF,";""linename?:?"?$0}'?/etc/passwd ...... filename?:?/etc/passwd;linenumber?:?32?;Total?number?of?columnsis?:7?;linename?:?abrt:x:173:173::/etc/abrt:/sbin/nologin filename?:?/etc/passwd;linenumber?:?33?;Total?number?of?columnsis?:7?;linename?:?sshd:x:74:74:Privilege-separated?SSH:/var/empty/sshd:/sbin/nologin filename?:?/etc/passwd;linenumber?:?34?;Total?number?of?columnsis?:7?;linename?:?tcpdump:x:72:72::/:/sbin/nologin filename?:?/etc/passwd;linenumber?:?35?;Total?number?of?columnsis?:7?;linename?:?justin:x:500:500:justin:/home/justin:/bin/bash
awk中執行linux的命令
awk可以用getline或system來調用shell的命令,在awk的print中我們可以直接調用shell命令,但都需要把命令放在雙引號里,如:END{print "\nIP:'$IP'";system("date")|getline d;print d;close("date")}' 或者END{print "\nIP:'$IP'";"date"|getline d;print d;close("date")}'
注意:1、在awk中打開一個管道,且同一時刻只能有一個管道存在。執行完一個命令,最好立即調用close()關閉管道。
? ? ? ? 2、getline?是awk里用于輸入重定向的一個函數,他可以從標準輸入/一個管道/文件讀取輸入,?而不只是從當前被處理的文件來處理,?他取得輸入的下一行并給NF,NR,FNR等內制變量置值,如果讀取成功,getline返回1;如果讀到文件結束符,getline返回0;如果發生錯誤,例如打不開文件,getline返回-1. 所以,getline可以用于while循環中;getline除了可以通過管道從shell命令里讀取數據外,它還可以從標準輸入(用"-"指定從標準輸入讀入,或者如果命令行沒有任何輸入文件且不用 重定向符"<"指定文件,默認也是從標準輸入讀)和文件里讀取數據;如果getline后面沒有指定變量,則讀取的數據會放到$0里面
? ? ? ? 3、system的返回值是cmd的退出狀態.如果要獲得cmd的輸出,就要和getline結合使用
? ? ? ? 4、如果system()括號里面的參數沒有加上雙引號的話,awk認為它是一個變量,它會從awk的變量里面把它們先置換為常量,然后再回傳給shell
如果system()括號里面的參數有加上雙引號的話,那么awk就直接把引號里面的內容回傳給shell,作為shell的“命令行”
? ? ? ? 5、system()是新開一個shell,在相應的cmdline參數送回給shell,所以要注意當前shell變量與新開shell變量環境變量的問題
awk使用shell變量及shell使用awk中的變量
調用shell腳本里面自定義變量
雙引號+單引號+雙引號+shell變量+雙引號+單引號+雙引號”的格式:awk '{print "'"$VAR1"'", "'"$VAR2"'"}' input_file ?
IP=`ifconfig?|grep?-i?"inet?addr"|grep?-v?"127.0.0.1"|awk?'{print?$2}'|awk?-F':'?'{print?$2}'|paste?-s?-d','` cat?/tmp/iptables.txt|awk?'BEGIN?{print?"\[流淚\]IPtalbes?Forward?Restart!\n"}?{print}?END{print?"\nIP:'$IP'";"date"|getline?d;print?d;close("date")}'shell中使用awk程序中定義的變量
例如:
eval $(awk 'BEGIN{print "var1='str1';var2='str2'"}')
或者eval $(awk '{printf("var1=%s; var2=%s; var3=%s;",$1,$2,$3)}' abc.txt)
之后可以在當前shell中使用var1,var2等變量了。
echo "var1=$var1 ----- var2=$var2"
一個檢測磁盤空間使用情況的腳本的例子
匹配操作符:
[root@justin?~]#?awk?"/root/"?/etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@justin?~]#?awk?"/^root/"?/etc/passwd root:x:0:0:root:/root:/bin/bash [root@justin?~]#?awk?-F?:?'/root/?{print?$1}'?/etc/passwd root operator [root@justin?~]#?awk?-F?:?'/root|justin/?{print?$1}'?/test.txt
范圍模版:
范圍模板匹配從第一個模板的第一次出現到第二個模板的第一次出現之間所有行。如果有一個模板沒出現,則匹配到開頭或末尾
[root@justin?~]#?touch?/home/passwd [root@justin?~]#?tail?-8?/etc/passwd?>?/home/passwd [root@justin?~]#?cat?!$ cat?/home/passwd pulse:x:497:496:PulseAudio?System?Daemon:/var/run/pulse:/sbin/nologin gdm:x:42:42::/var/lib/gdm:/sbin/nologin rpcuser:x:29:29:RPC?Service?User:/var/lib/nfs:/sbin/nologin nfsnobody:x:65534:65534:Anonymous?NFS?User:/var/lib/nfs:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin sshd:x:74:74:Privilege-separated?SSH:/var/empty/sshd:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin justin:x:500:500:justin:/home/justin:/bin/bash [root@justin?~]#?awk?"/gdm/,/sshd/"?/home/passwd gdm:x:42:42::/var/lib/gdm:/sbin/nologin rpcuser:x:29:29:RPC?Service?User:/var/lib/nfs:/sbin/nologin nfsnobody:x:65534:65534:Anonymous?NFS?User:/var/lib/nfs:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin sshd:x:74:74:Privilege-separated?SSH:/var/empty/sshd:/sbin/nologin [root@justin?~]#
獲得外部變量
在awk中,變量不需要定義就可以直接使用,變量類型可以是數字或字符串。
賦值格式:Variable = expression,如$ awk '$1 ~/test/{count = $2 + $3; print count}' test,上式的作用是,awk先掃描第一個域,一旦test匹配,就把第二個域的值加上第三個域的值,并把結果賦值給變量count,最后打印出來。
awk可以在命令行中給變量賦值,然后將這個變量傳輸給awk腳本。如$ awk -F: -f awkscript month=4 year=2004 test,上式的month和year都是自定義變量,分別被賦值為4和2004。在awk腳本中,這些變量使用起來就象是在腳本中建立的一樣。注意,如果參數前面出現test,那么在BEGIN語句中的變量就不能被使用。
域變量也可被賦值和修改,如$ awk '{$2 = 100 + $1; print }' test,上式表示,如果第二個域不存在,awk將計算表達式100加$1的值,并將其賦值給$2,如果第二個域存在,則用表達式的值覆蓋$2原來的值。再例如:$ awk '$1 == "root"{$1 ="test";print}' test,如果第一個域的值是“root”,則把它賦值為“test”,注意,字符串一定要用雙引號。
內建變量的使用。變量列表在前面已列出,現在舉個例子說明一下。$ awk -F: '{IGNORECASE=1; $1 == "MARY"{print NR,$1,$2,$NF}'test,把IGNORECASE設為1代表忽略大小寫,打印第一個域是mary的記錄數、第一個域、第二個域和最后一個域。
fflush函數用以刷新輸出緩沖區,如果沒有參數,就刷新標準輸出的緩沖區,如果以空字符串為參數,如fflush(""),則刷新所有文件和管道的輸出緩沖區。
運算符:
= += -= *= /= %= ^= **= ? 賦值 ?
|| ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 邏輯或 ?
&& ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?邏輯與 ?
[root@Super?~]#?cat?sed.txt?|awk?'/GSSAPIAuthentication?no/||/GSSAPIAuthentication?yes/?{print?$0}' GSSAPIAuthentication?no?GSSAPIAuthentication?yes GSSAPIAuthentication?yes [root@Super?~]#?cat?sed.txt?|awk?'/GSSAPIAuthentication?no/&&/GSSAPIAuthentication?yes/?{print?$0}' GSSAPIAuthentication?no?GSSAPIAuthentication?yes [root@Super?~]#?cat?sed.txt? GSSAPIAuthentication?no?GSSAPIAuthentication?yes GSSAPIAuthentication?yes [root@Super?~]#~和 ~! ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 匹配后面的正則表達式和不匹配正則表達式;awk '$1 ~ /101/ {print $1}' file 顯示文件中第一個域匹配101的行(記錄),并打印第一個域
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?netstat -tnlp|egrep -i "$1"|awk {'print $4'}|awk -F':' '{if ($NF~/^[0-9]*$/) print $NF}'|sort |uniq 2>/dev/null,其中$NF~/^[0-9]*$/表示最后一個域匹配的是數字
< <= > >= != == ? ? ? ? ? ? ? ? 關系運算符 ?
空格 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 連接 ?
+ - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?加,減 ?
* / & ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 乘,除與求余 ?
+ - ! ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 一元加,減和邏輯非 ?
^ *** ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?求冪 ?
++ -- ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 增加或減少,作為前綴或后綴 ?
$ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 字段引用 ,$NF表示最后一個域 ?
[root@justin?~]#?awk?-F:?'/root/?&&?/bash/?{print?$0}'?/etc/passwd root:x:0:0:root:/root:/bin/bash [root@justin?~]#?awk?-F:?'/root/?{print?$0}'?/etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@justin?~]#?awk?-F:?'$1=="tcpdump"'?/etc/passwd tcpdump:x:72:72::/:/sbin/nologin [root@justin?~]#?awk?-F:?'$3>499?||?$4<1'?/etc/passwd root:x:0:0:root:/root:/bin/bash sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt operator:x:11:0:operator:/root:/sbin/nologin nfsnobody:x:65534:65534:Anonymous?NFS?User:/var/lib/nfs:/sbin/nologin justin:x:500:500:justin:/home/justin:/bin/bash [root@justin?~]#
函數
print函數的參數可以是變量、數值或者字符串。字符串必須用雙引號引用,參數用逗號分隔。如果沒有逗號,參數就串聯在一起而無法區分。這里,逗號的作用與輸出文件的分隔符的作用是一樣的,只是后者是空格而已。
gsub
gsub(r,s)??? 在整個$0中用s替代r
gsub(r,s,t)??? 在整個t中用s替代r
將一行拆分成多行
[root@localhost?~]#?cat?test? 1,2,3 a,b,c [root@localhost?~]#拆分后
[root@localhost?~]#?cat?test? 1 1 2 1 3 1 a 2 b 2 c 2 [root@localhost?~]#解析:
先在每行末加個逗號“,”,不然每行的最后一位數3和c后面的1和2就沒有
[root@localhost?~]#?sed?-i?'s/$/,/'?test? [root@localhost?~]#?cat?test? 1,2,3, a,b,c, [root@localhost?~]#?cat?test?|?awk?'BEGIN{i=1}{gsub(/,/,"\t"i"\n");i++;print}' 1 1 2 1 3 1a 2 b 2 c 2[root@localhost?~]#?cat?test?|?awk?'BEGIN{i=1}{gsub(/,/,"\t"i"\n");i++;print}'|sed?'/^$/d' 1 1 2 1 3 1 a 2 b 2 c 2 [root@localhost?~]#gsub(regular expression, subsitution string, target string);簡稱 gsub(r,s,t),gsub函數則使得在所有正則表達式被匹配的時候都發生替換
[root@localhost?~]#?echo?"a?b?c?2011-11-22?a:d"?|?awk?'$4=gsub(/-/,"",$4)' a?b?c?2?a:d [root@localhost?~]#?echo?"a?b?c?2011-11-22?a:d"?|?awk?'gsub(/-/,"",$4)' a?b?c?20111122?a:d [root@localhost?~]#?echo?"a?b?c?2011-11-22?a:d"?|?awk?'gsub(/-/,"_",$4)' a?b?c?2011_11_22?a:d [root@localhost?~]#?echo?"a?b?c?2011-11-22?a:d"?|?awk?'gsub(/-/,"_")' a?b?c?2011_11_22?a:d [root@localhost?~]#gsub(/-/,"",$4)的值是2【在賦值的情況下是這樣的~】,你將2賦值給$4 ,gsub返回的是替換的次數
[root@localhost?~]#?cat?data.test? 0001|123efskjfdj|EREADFASDLKJCV 0002|123456djfksdaa|JDKFJALSDJFsddf 0003|12345678efskjfdj|EREADFASDLKJCV 0004|123456789djfksdaa1234|JDKFJALSDJFsddf [root@localhost?~]#?awk?-F'|'?'BEGIN{OFS="|"}{sub(/[0-9]+/,"",$2);print?$0}'?data.test? 0001|efskjfdj|EREADFASDLKJCV 0002|djfksdaa|JDKFJALSDJFsddf 0003|efskjfdj|EREADFASDLKJCV 0004|djfksdaa1234|JDKFJALSDJFsddf [root@localhost?~]#?awk?-F'|'?'BEGIN{OFS="|"}{sub(/[0-9]+5/,"",$2);print?$0}'?data.test??#0-9出現任意次數,后面跟隨5的替換?$2匹配的第二個域 0001|123efskjfdj|EREADFASDLKJCV 0002|6djfksdaa|JDKFJALSDJFsddf 0003|678efskjfdj|EREADFASDLKJCV 0004|6789djfksdaa1234|JDKFJALSDJFsddf [root@localhost?~]#?awk?-F'|'?'BEGIN{OFS="|"}{sub(/[0-9]+2/,"2018",$1);print?$0}'?data.test? 0001|123efskjfdj|EREADFASDLKJCV 2018|123456djfksdaa|JDKFJALSDJFsddf 0003|12345678efskjfdj|EREADFASDLKJCV 0004|123456789djfksdaa1234|JDKFJALSDJFsddf [root@localhost?~]#gsub匹配所有的符合模式的字符串,相當于 sed 's//g' 。
sub匹配第一次出現的符合模式的字符串,相當于 sed 's//' 。
sub函數匹配指定域/記錄中最大、最靠左邊的子字符串的正則表達式,并用替換字符串替換這些字符串。如果沒有指定目標字符串就默認使用整個記錄。替換只發生在第一次匹配的時候
$ awk '{ sub(/test/, "mytest"); print }' testfile #在整個記錄中匹配,替換只發生在第一次匹配發生的時候。
$ awk '{ sub(/test/, "mytest", $1); print }' testfile ?#在整個記錄的第一個域中進行匹配,替換只發生在第一次匹配
$ awk '{ gsub(/test/, "mytest"); print }' testfile #在整個文檔中匹配test,匹配的都被替換成mytest。
$ awk '{ gsub(/test/, "mytest", $1); print }' testfile #在整個文檔的第一個域中匹配,所有匹配的都被替換成mytest
例如:截取路徑部分的目錄
[root@localhost?~]#?cat?gsub.txt? serv_dir=/home/level2/ini/netunitht.xml serv_dir=/home/level2/rawfiles/publicch/proxy_sysht.zip serv_dir=/home/level2/user/userini/dzhhqserverht.ini serv_dir=/home/level2/user/userini/autoupdateht.ini [root@localhost?~]#?cat?gsub.txt?|?sed?"s/^.*=//"|awk?-F'/'?'{gsub($NF,"");print}'|sort?-bu /home/level2/ini/ /home/level2/rawfiles/publicch/ /home/level2/user/userini/ [root@localhost?~]#在賦值的情況下gsub返回的是替換的次數
[root@localhost?~]#?echo?"a?b?c?2011-11-22?a:d"?|?awk?'$4=gsub(/-/,"",$4)' a?b?c?2?a:d [root@localhost?~]#gsub(/-/,"",$4)的值是2
length?
length函數返回沒有參數的字符串的長度。length函數返回整個記錄中的字符數,length($n)返回弟n個域的字符串長度
echo "1234567"|awk '{print length}'
[root@localhost?~]#?echo?"1234567"|awk?'{print?length}' 7 [root@Super?~]#?awk?-F'='?'length($2)<7{print?$2}'?test.txt? dweere [root@Super?~]#?cat?test.txt? adfa=dweere=dabw3d=kj8kjfadf [root@Super?~]#?awk?-F'='?'length($2)<7{print?$2"\t"length($2)}'?test.txt? dweere 6 [root@Super?~]#?awk?-F'='?'{if(length($2)<7)?print?$2"\t"length($2)}'?test.txt? dweere 6 [root@Super?~]#index
index(String1,String12)? 在由 String1 參數指定的字符串(其中有出現 String2 指定的參數)中,返回位置,從 1 開始編號。如果 String2 參數不在 String1 參數中出現,則返回 0(零)。
index( String1, String2 )
blength
blength [(String)] ?? ?返回 String 參數指定的字符串的長度(以字節為單位)。如果未給出 String 參數,則返回整個記錄的長度($0 記錄變量)。
match
match(s,r)??? 測試s是否包含匹配r的字符串
tolower
tolower( String ) ?? ?返回 String 參數指定的字符串,字符串中每個大寫字符將更改為小寫。大寫和小寫的映射由當前語言環境的 LC_CTYPE 范疇定義。
toupper( String ) ?? ?返回 String 參數指定的字符串,字符串中每個小寫字符將更改為大寫。大寫和小寫的映射由當前語言環境的 LC_CTYPE 范疇定義。
sprintf
sprintf(Format, Expr, Expr, … ) ?? ?根據 Format 參數指定的 printf 子例程格式字符串來格式化 Expr 參數指定的表達式并返回最后生成的字符串。
gensub
gensub(a,b,c[,d])全局替換,匹配正則a, 用b替換,c為指定替換目標是第幾次匹配,d為指定替換目標是哪個域如$1,$2,若無d指$0,返回值為target替換后內容(未替換還是返回 target原內容),與sub、gsub不同的是,target內容替換后不改變
eg:
gensub(/123/,"x",1,$1)替換$1中 第一次匹配到的123為字符x,返回值為$1替換后的內容,且$1的內容并沒有改變
gensub(/a(.*)b/,"\\1",1) 返回值為匹配正則第1對()內的內容
gensub(/a(.*)b(.*)c/,"\\2",1) 返回值為匹配正則第2對()內的內容
substr
截取字符串,返回從起始位置起,指定長度之子字符串;若未指定長度,則返回從起始位置到字符串末尾的子字符串。
格式:
? substr(s,p) 返回字符串s中從第p個字符串開始到結尾的后綴部分
? substr(s,p,n) 返回字符串s中從第p個字符串開始長度為n的后綴部分
[root@localhost?~]#?echo?"1234|abcd|ab12"|awk?'{print?substr($0,6,4)}'?#返回從第6個字符串開始長度為4的部分 abcd [root@localhost?~]#?echo?"1234|abcd|ab12"|awk?'{print?substr($0,6,8)}'? abcd|ab1 [root@localhost?~]#?echo?"1234|abcd|ab12"|awk?-F'|'?'{print?substr($3,2,2)}'?#返回以|為分隔符的第3個域的第2個字符串開始長度為2的部分 b1 [root@localhost?~]#?echo?"1234|abcd|ab12"|awk?-F'|'?'{print?substr($3,2)}'???#返回以|為分隔符的第3個域的第2個字符串到字符串末尾的部分 b12 [root@localhost?~]#?cat?substr.txt? 115!16201!1174113017250745?10.86.96.41?211.140.16.1?200703180718 F125!16202!1174113327151715?10.86.96.42?211.140.16.2?200703180728 F235!16203!1174113737250745?10.86.96.43?211.140.16.3?200703180738 F245!16204!1174113847250745?10.86.96.44?211.140.16.4?200703180748 F355!16205!1174115827252725?10.86.96.45?211.140.16.5?200703180758 [root@localhost?~]#?awk?-F'!'?'{?print?substr($3,6,11)}'?substr.txt? 13017250745 13327151715 13737250745 13847250745 15827252725 [root@localhost?~]#split
初始化和類型強制,awk的內建函數split允許你把一個字符串分隔為單詞并存儲在數組中。你可以自己定義域分隔符或者使用現在FS(域分隔符)的值。
格式:
? ?split (string, array, field separator)
? ?split (string, array) -->如果第三個參數沒有提供,awk就默認使用當前FS值。
[root@localhost?~]#?time="12:34:56" [root@localhost?~]#?out=`echo?$time?|?awk?'{split($0,a,":");print?a[1],a[2],a[3]}'` [root@localhost?~]#?echo?$out 12?34?56 [root@localhost?~]#?cat?out-130.log +08:00?2019-01-08?11:59:30.935?:?task:nw.platform.wizards_securities-SqlReader0057?;?cost:24?ms?;?size:0?;?tmstamp:5069194669-5069195668 +08:00?2019-01-08?12:59:30.938?:?task:nw.platform.wizards_securities-SqlReader0057?;?cost:3?ms?;?mark:0?;?last:5069194668 +08:00?2019-01-08?13:59:30.989?:?task:nw.platform.wizards_securities-SqlReaderPersonalName?;?cost:81?ms?;?size:0?;?tmstamp:5075630629-5075631628 +08:00?2019-01-08?13:59:30.992?:?task:nw.platform.wizards_securities-SqlReaderPersonalName?;?cost:3?ms?;?mark:0?;?last:5075630628 +08:00?2019-01-08?14:59:31.345?:?task:nw.platform.wizards_securities-SqlReader0057?;?cost:443?ms?;?size:0?;?tmstamp:5069194669-5069195668 +08:00?2019-01-08?15:59:31.347?:?task:nw.platform.wizards_securities-SqlReader0057?;?cost:2?ms?;?mark:0?;?last:5069194668 [root@localhost?~]#?cat?out-130.log?|grep?'2019-01-08'|awk?'{split($3,A,":");if(A[1]>="13"?&&?A[1]<"14"){print?$0}}'???//過濾13-14點的日志 +08:00?2019-01-08?13:59:30.989?:?task:nw.platform.wizards_securities-SqlReaderPersonalName?;?cost:81?ms?;?size:0?;?tmstamp:5075630629-5075631628 +08:00?2019-01-08?13:59:30.992?:?task:nw.platform.wizards_securities-SqlReaderPersonalName?;?cost:3?ms?;?mark:0?;?last:5075630628 [root@localhost?~]#?cat?awk.txt [22/Feb/2017-18:51:21]????api.momo.com????/api/feed????HTTP/1.1??????121.0.0.1????iphone1.1 [root@localhost?~]#?cat?awk.txt|awk?'{split($1,array,"[");split(array[2],array2,"]");if(array2[1]?>=?"22/Feb/2017-18:52:59"){print($0)}}systime、strftime
systime函數將返回自1970 年1月l日以來經過的時間(按秒計算)。
[root@localhost?~]#?date Tue?May?22?19:35:29?CST?2018 [root@localhost?~]#?awk?'BEGIN{a=systime();print?a}' 1526988930 [root@localhost?~]#strftime函數使用C庫中的strftime函數對時間進行格式化。格式形式可以為%T %D等(參見下表)。時間戳的格式和systime函數返回值所采用的格式一樣,如果不使用時間戳,則以當前的時間為默認時間。
[root@localhost?~]#?awk?'BEGIN{a=strftime("%c");print?a}' Tue?22?May?2018?07:37:27?PM?CST [root@localhost?~]#?awk?'BEGIN{a=strftime("%m%d%y");print?a}' 052218 [root@localhost?~]#?awk?'BEGIN{a=strftime("%m%d%Y");print?a}' 05222018 [root@localhost?~]#日期格式定義
%a簡寫的星期名(如Sun)
%A完整的星期名(如Sunday)
%b簡寫的月名(如Oct)
%B完整的月名(如October)
%c本地的日期和時間(如Sun Oct 17 15:26:46 2014)
%d用十進制表示的月份中的某一夭( 如17)
%D采用10/17/14 形式表示的日期
%e月份中的某一夭,如果只有一位數字,用空格填充份
%H用十進制表示的24 小時制的小時數以( 如15)
%I用十進制表示的12 小時制的小時數( 如03)
%j用十進制表示的從當年1 月1 日以來的天數。(如290)
%m用十進制表示的月數( 如10)
%M用十進制表示的分鐘數( 如26)
%p采用12 小時制表示的AM/PM 表示法(如PM)
%S用十進制表示的秒數(如26)
%U用十進制表示的一年中的周數(星期日作為一周的開始)(如42)
%w用十進制表示的星期數(如星期日為0)
%W用十進制表示的一年中的周數(星期一作為一周的開始)(如41)
%x本地日期(如 10/17/14)
%X本地時間(如15:26:26)
%y用十進制表示的年份(采用兩位十進制表示,如14)
%Y帶世紀的年份(如2004)
%Z時間區(如PDT)
%%一個百分號字符標記(%)
幾個實例
$ awk '/^(no|so)/' test-----打印所有以模式no或so開頭的行。
$ awk '/^[ns]/{print $1}' test-----如果記錄以n或s開頭,就打印這個記錄。
$ awk '$1 ~/[0-9][0-9]$/(print $1}' test-----如果第一個域以兩個數字結束就打印這個記錄。
$ awk '$1 == 100 || $2 < 50' test-----如果第一個或等于100或者第二個域小于50,則打印該行。
$ awk '$1 != 10' test-----如果第一個域不等于10就打印該行。
$ awk '/test/{print $1 + 10}' test-----如果記錄包含正則表達式test,則第一個域加10并打印出來。
$ awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' test-----如果第一個域大于5則打印問號后面的表達式值,否則打印冒號后面的表達式值。
$ awk '/^root/,/^mysql/' test----打印以正則表達式root開頭的記錄到以正則表達式mysql開頭的記錄范圍內的所有記錄。如果找到一個新的正則表達式root開頭的記錄,則繼續打印直到下一個以正則表達式mysql開頭的記錄為止,或到文件末尾。
?if語句
格式:
? ? ? ?{if (expression){
? ? ? ? ? ? ? ? ? 語句; 語句; ...
? ? ? ? ? ? ? ? ? ? }
? ? ? ?}
$ awk '{if ($1 <$2) print $2 "too high"}' test。如果第一個域小于第二個域則打印。
$ awk '{if ($1 < $2) {count++; print "ok"}}' test.如果第一個域小于第二個域,則count加一,并打印ok。
注意:1、if 條件后面的語句塊,如果是單個語句,可以省略花括號,如果是多個語句,必須用花括號
2、awk對大括號和語句的位置沒有特殊的要求(和sed不同)。左大括號放在條件表達式后面,可以與條件表達式位于一行也可以在下一行。第一條語句可以緊跟左大括號或從下一行開始,右大括號可以與最后一條語句位于同一行也可以在下一行。在大括號的前后允許有空格或制表符。雖然沒有要求語句縮進書寫,但這樣可以改善可讀性。
[root@localhost?~]#?cat?mul.txt? ABCD?1234?ab?cd ABC?5678?12?3c? ab?1234?3d?45 AB?12?ab?cd ab?CD?12?34? [root@localhost?~]#?awk?'{if($2==1234){print?$1,$NF}}'?mul.txt? ABCD?cd ab?45 [root@localhost?~]#?if/else語句,用于雙重判斷
格式:
? ? ? ?{if (expression){statement; statement; ...}
? ? ? ?else{statement; statement; ...}
? ? ? ?}
$ awk '{if ($1 > 100) print $1 "bad" ; else print "ok"}' test。如果$1大于100則打印$1 bad,否則打印ok。
$ awk '{if ($1 > 100){ count++; print $1} else {count--; print $2}' test。如果$1大于100,則count加一,并打印$1,否則count減一,并打印$1。
注意:if 條件后面的語句塊,如果是單個語句,可以省略花括號,如果是多個語句,必須用花括號
if/else else if語句,用于多重判斷
格式:
? ? ? ?{if (expression){statement; statement; ...}
? ? ? ?else if (expression){statement; statement; ...}
? ? ? ?else if (expression){statement; statement; ...}
? ? ? ?else {statement; statement; ...}
? ? ? ?}
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"
循環
awk有三種循環:while循環;for循環;special for循環。
while循環:
使用while循環的時候第一步先給一個變量設初始值。然后在while表達式中測試該變量。
$ awk '{ i = 1; while ( i <= NF ) { print NF,$i; i++}}' test。變量的初始值為1,若i小于可等于NF(記錄中域的個數),則執行打印語句,且i增加1。直到i的值大于NF.
for循環
$ awk '{for (i = 1; i<NF; i++) print NF,$i}' test。作用同上。
$awk '{for(i=2;i<17;i++) {printf("%s ",$i)} print $NF"\n"}'???????? 輸出連續的多列
break、continue語句:
break用于在滿足條件的情況下跳出循環;continue用于在滿足條件的情況下忽略后面的語句,直接返回循環的頂端。如:
{for ( x=3; x<=NF; x++)
? ? ? ? ? ?if ($x<0){print "Bottomed out!"; break}}
{for ( x=3; x<=NF; x++)
? ? ? ? ? ?if ($x==0){print "Get next item"; continue}} ? ??
next語句從輸入文件中讀取一行,然后從頭開始執行awk腳本。如:
{if ($1 ~/test/){next}
? ?else {print}
} ? ?
exit語句用于結束awk程序,但不會略過END塊。退出狀態為0代表成功,非零值表示出錯。
待完善......
轉載于:https://blog.51cto.com/ityunwei2017/1334886
總結
以上是生活随笔為你收集整理的RHEL6基础三十一之服务器维护基础命令②awk的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 巷子里的人指什么
- 下一篇: OpenStack Heat服务介绍 (