文本處理小工具
tr
從標準輸入中替換、縮減和/或刪除字符,并將結果寫到標準輸出。
? -c:取字符集的補集
? -d:刪除所有屬于第一字符集的字符
? -s:把連續重復的字符以單獨一個字符表示(壓縮)
? -t:將第一個字符集對應字符轉化為第二字符集對應的字符
#echo 'tank zhang' |tr a-z A-Z TANK ZHANG #cat > aaa.txt aaa ? bbb ? #cat aaa.txt|tr 'a' 'c' ccc ? bbb ? #cat aaa.txt|tr -d 'a' ? bbb ? #cat aaa.txt|tr -s '\n' aaa bbb ?
cut
cut – 在文件的每一行中提取片斷
在每個文件 FILE 的各行中, 把提取的片斷顯示在標準輸出.
? -d:指定分割符
? -f:指定打印的段落
sort
串聯排序所有指定文件并將結果寫到標準輸出。
? -n:按大小進行排序 -r:倒序 -k:按那一個字段進行排序 sort -t: -k3 -n /etc/passwd #按照第三列數字大小正序排列 sort -t: -k3 -nr /etc/passwd #按照第三列數字大小逆序排列 seq 102 |sort -R |head -n1 cut -d: -f1,3 /etc/passwd |sort -t: -k2 -nr
uniq
從輸入文件或者標準輸入中篩選相鄰的匹配行并寫入到輸出文件或標準輸出。
? -c:統計重復個數,并打印重復個數
? diff:文件不同點對比
? patch:給文件打補丁 patch -p1 FILE1 < FILE2 //使用FILE1給FILE2進行打補丁
提取前10位訪問量的用戶IP 答案:cat /var/log/httpd/access_log |cut -d " " -f1 |sort |uniq -c \sort -nr |head -n10 統計遠程主機登陸的前三名 答案:#last | tr -s " " ":"|cut -d: -f3|tr -d "[:alpha:]"|sort -nr|uniq -c|head -n -3|sort -t" " -k1 -nr ? 練習: 1、找出ifconfig “網卡名” 命令結果中本機的IPv4地址 答案:CentOS6:ifconfig eth0 |head -n2|tail -n1|tr -s " "|cut -d: -f4 答案:CentOS7:ifconfig ens33|head -n2|tail -n1|tr -s " "|cut -d " " -f3 2、查出分區空間使用率的最大百分比值 答案:df |tr -s " " %|cut -d% -f5 |sort -nr |head -n1 3、查出用戶UID最大值的用戶名、UID及shell類型 答案:#cat /etc/passwd|cut -d: -f1,3,7|sort -t: -k2 -nr|head -n 1 4、查出/tmp的權限,以數字方式顯示 答案: 5、統計當前連接本機的每個遠程主機的連接數,并按從大到小排序 答案:#netstat -nt |tr -d "[:alpha:]()/-"|tr -s " " ":"|cut -d: -f6 |sort -nr|uniq -c|head -n -1|sort -t" " -k1 -nr ?
Linux文本處理三劍客
grep
grep的工作方式,它在一個或多個文件中搜索字符串模板。如果模板包括空格,則必須被引用,模板后的所有字符串被看作文件名。搜索的結果被送到屏幕,不影響原文件內容。
-E:使用擴展正則表達式 -R:不使用正則表達式 -v:顯示不被pattern匹配到的行 -o:僅顯示匹配到的字符串 -i:忽略大小寫 -n:顯示匹配的行號 -c: 統計匹配的行數 -A n:打印匹配行的后幾行 -B n:打印匹配行的前幾行 -C n:打印匹配行的前后幾行
-w:匹配整個單詞
-xz:匹配整行
? 取所有的IP地址:ifconfig ens33 |grep -o "[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}" ? 取當前系統的IP地址:ifconfig ens33| grep -o "inet [0-9.]\+"|cut -d " " -f2 ? 顯示系統的版本號: ? cat /etc/redhat-release |grep -o "[0-9]\+"|head -n1 ? 過濾空行:grep -v ”^[[:space:]]*$“ f1 ? ? 查出分區空間使用率的最大百分比值 ? 答案:df |grep "/dev/sd" |grep -o "[0-9]\{1,3\}%"|sort -nr|head -n1 ? 練習: 9、顯示/proc/meminfo文件中以大小s開頭的行(要求:使用兩種方法) 答案: grep -i "^s" /proc/meminfo ? ? grep "^[sS].*" /proc/meminfo 10、顯示/etc/passwd文件中不以/bin/bash結尾的行 答案:cat /etc/passwd | grep -v "/bin/bash$" 11、顯示用戶rpc默認的shell程序 答案:cat /etc/passwd |grep "^rpc\>" |cut -d: -f7 12、找出/etc/passwd中的兩位或三位數 答案:cat /etc/passwd | grep -wo "[[:digit:]]\{2,3\}" 13、顯示CentOS7的/etc/grub2.cfg文件中,至少以一個空白字符開頭的且后面有非空白字符的行 答案:cat /etc/grub2.cfg |grep "^[[:space:]].*[^[:space:]].*" 14、找出“netstat -tan”命令結果中以LISTEN后跟任意多個空白字符結尾的行 答案:netstat -tan |grep "LISTEN[[:space:]]*$" 15、顯示CentOS7上所有系統用戶的用戶名和UID 答案:cat /etc/passwd | cut -d: -f1,3 | grep ":[1-9][0-9]\{,2\}$" 16、添加用戶bash、testbash、basher、sh、nologin(其shell為/sbin/nologin),找出/etc/passwd用戶名和shell同名的行 答案:cat /etc/passwd | grep "^\(.\+\):.*/\1$" ? 或cat /etc/passwd | grep "^\(.*\):.*/\1$" 17、利用df和grep,取出磁盤各分區利用率,并從大到小排序 答案:df | grep “/dev/sd” | grep -o “[0-9]*%” | sort -nr 18、顯示三個用戶root、mage、wang的UID和默認shell 答案:cat /etc/passwd |grep -E "^(wang |mage|root)\>" |cut -d: -f1,,3,7 19、找出/etc/rc.d/init.d/functions文件中行首為某單詞(包括下劃線)后面跟一個小括號的行 答案:cat /etc/rc.d/init.d/functions |grep "^[[:alpha:]_].*()" 20、使用egrep取出/etc/rc.d/init.d/functions中其基名 答案:echo /etc/rc.d/init.d/functions |egrep -o "[^/]*/?$" ? ? 21、使用egrep取出上面路徑的目錄名 答案:echo /etc/rc.d/init.d/functions |egrep -o "^/.*/" 22、統計last命令中以root登錄的每個主機地址登錄次數 答案:last | egrep root | egrep -wo ”[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+“ | uniq -c | sort -nr 23、利用擴展正則表達式分別表示0-9、10-99、100-199、200-249、250-255 答案:egrep -o "([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))" 24、顯示ifconfig命令結果中所有IPv4地址 答案:ifconfig |egrep -o "\<(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>" ? 25、將此字符串:welcome to magedu linux 中的每個字符去重并排序,重復次數多的排到前面 答案:echo "welcome to magedu linux" |grep -o . |sort |uniq -c |sort -nr 26、復制/etc/profile至/tmp/目錄,用查找替換命令刪除/tmp/profile文件中的行首的空白字符 答案:cp /etc/profile /tmp/ |grep -o "^[:blank:].*" | 27、復制/etc/rc.d/init.d/functions文件至/tmp目錄,用查找替換命令為 /tmp/functions的每行開頭為空白字符的行的行首添加一個#號 答案:# :%s/^[[:space:]]/#&/g ^[[:space:]] 為標準的正則表達式,匹配的是以空白開頭的行 28、在vim中設置tab縮進為4個字符 答案:# set ts=4 29、復制/etc/rc.d/init.d/functions文件至/tmp目錄,替換/tmp/functions文件中的/etc/sysconfig/init為/var/log 答案:cp /etc/rc.d/init.d/functions /tmp ? ? %s@/etc/sysconfig/init@/var/log 30、刪除/tmp/functions文件中所有以#開頭,且#后面至少有一個空白字符的行的行首的#號 答案:%s/^# \+//g 注意+號前面的轉義字符 ?
sed
行編輯器,流處理器
sed之所以能以行為單位的編輯或修改文本,其原因在于它使用了兩個空間:一個是活動的“模式空間(pattern space)”,另一個是起輔助作用的“保持空間(hold space)這2個空間的使用。
模式空間:可以想成工程里面的流水線,數據之間在它上面進行處理。 保持空間:可以想象成倉庫,我們在進行數據處理的時候,作為數據的暫存區域。
正常情況下,如果不顯示使用某些高級命令,保持空間不會使用到!
sed在正常情況下,將處理的行讀入模式空間,腳本中的“sed command(sed命令)”就一條接著一條進行處理,直到腳本執行完畢。然后該行被輸出,模式被清空;接著,在重復執行剛才的動作,文件中的新的一行被讀入,直到文件處理完畢。
sed語法:sed [option]…’script’ inputfile…. sed常用選項 -n:不輸出模式空間內容到屏幕,即不自動打印 -i.bak //備份原有文件FILE.bak -r:支持使用擴展正則表達式 -e:多點編輯 -f:/PATH/SCRIPT_FILE 從指定文件中讀取編輯腳本 sed的編輯命令 d:刪除指定行 p:打印模式空間的內容 a []text:在指定行之后追加文本,可以使用/n進行換行 sed ‘2,5a\ ===’ f1 #在第二行到第五行之后插入空格加等號 i []text:在指定的之前添加文本 sed -i.bak ‘/aliases/aalias p=poweroff’ .bashrc sed -i.bak ‘/aliases/aalias cdnet=”cd /etc/sysconfig/network-scrts/”‘ .bashrc c []text:替換指定行 w /PATH/SOMEFILE:將匹配的行保存在指定文件 r /PATH/SOMFILE:讀取指定的文件到模式空間中的指定位置 =:為模式空間匹配的行打印行號 ! :模式空間中匹配行取反處理
? s///:查找替換,指出使用其它分隔符,s@@@,s### g:全局替換 p:打印 w /PATH/TO/SOMEFILE:將替換成功的行保存在指定文件中
sed示例一: ?sed ‘2p’ /etc/passwd ?sed –n ‘2p’ /etc/passwd ?sed –n ‘1,4p’ /etc/passwd ?sed –n ‘/root/p’ /etc/passwd ?sed –n ‘2,/root/p’ /etc/passwd 從2行開始 ?sed -n ‘/^$/=’ file 顯示空行行號 ?sed –n –e ‘/^$/p’ –e ‘/^$/=’ file ?sed ‘/root/a\superman’ /etc/passwd行后 ?sed ‘/root/i\superman’ /etc/passwd 行前 ?sed ‘/root/c\superman’ /etc/passwd 代替行 ?sed ‘/^$/d’ file ?sed ‘1,10d’ file ?nl /etc/passwd | sed ‘2,5d’ ?nl /etc/passwd | sed ‘2a tea’ ?sed 's/test/mytest/g' example ?sed –n ‘s/root/&superman/p’ /etc/passwd 單詞后 ?sed –n ‘s/root/superman&/p’ /etc/passwd 單詞前 ?sed -e ‘s/dog/cat/’ -e ‘s/hi/lo/’ pets ?sed –i.bak ‘s/dog/cat/g’ pets
示例二: sed 's/root/administrator/g' /etc/passwd sed -r 's/(root)/\1er/g' /etc/passwd ? ? #-r指擴展的正則表達式 sed -r 's/(root)/admin\1/g' /etc/passwd sed -r 's/(.*)/\1magedu/' /etc/passwd ? sed -r 's@/bin/bash$@/sbin/bash@' /etc/passwd sed -r 's@/(/bin/bash)$@/s\1@' /etc/passwd sed -r '/GRUB_CMDLINE_LINUX/s/(.*)"$/\1 xyz"/' /etc/default/grub sed -r '/GRUB_CMDLINE_LINUX/s/(.*)"$/ xyz"/' /etc/default/grub sed -r 's/(GRUB_CMDLINE_LINUX.*)"$/\1 xyz"/' /etc/default/grub ? ifconfig ens33|sed -n '2p' | sed -r 's@.*inet(.*).*@\1@' ? ifconfig ens33|sed -n '2p' | sed -r 's@(.*inet)(.*)( net.*)@\2@' ifconfig ens33|sed -r '2!d:s@(.*inet)(.*)( net.*)@\2@' ifconfig ens33|sed -n '2p' |sed 's/.*int //' |sed 's/ netmask.*//' ifconfig ens33|sed -n '2p' |sed -e 's/.*inet //' -e 's/ netmask.*//' 去掉前面的注釋:sed -e '/^#NameVirtual/s/#//' -e '/^<VirtualHost/,/^#^<\/VirtualHost/s/#//' /etc/httpd/conf/httpd.conf 取目錄名:echo "/etc/sysconfig/network/" |sed -r 's/(.*\/)([^/]+\/?$)/\1' 取基名:echo "/etc/sysconfig/network/" |sed -r 's/(.*\/)([^/]+\/?$)/\2/'
? 高級編輯命令
? P:打印模式空間開端至\n內容,并追加到默認輸出之前 g:[address[,address]]g 將hold space中的內容拷貝到pattern space中,原來pattern space里的內容清除。
? G:[address[,address]]G 將hold space中的內容append到pattern space\n后。 h:[address[,address]]h 將pattern space中的內容拷貝到hold space中,原來的hold space里的內容被清除。 H:[address[,address]]H 將pattern space中的內容append到hold space\n后。 d:[address[,address]]d 刪除pattern中的所有行,并讀入下一新行到pattern中。 D:[address[,address]]D 如果模式空間包含換行符,則刪除直到第一個換行符的模式空間中的文本,并不會讀取新的輸入行,而使用合成的模式空間重新啟動循環。如果模式空間不包含換行符,則會像發出d命令那樣啟動正常的新循環 x:交換保持空間和模式空間的內容。?
sed示例三: ?sed -n 'n;p' FILE #打印偶數行 ?sed '1!G;h;$!d' FILE #倒敘顯示 ?sed 'N;D‘ FILE #只留最后一行 ?sed '$!N;$!D' FILE #只留下倒數兩行 ?sed '$!d' FILE #只留最后一行 ?sed ‘G’ FILE #輸出結果中間加空行 ?sed ‘g’ FILE #刪除全部數據,但位置不變 ?sed ‘/^$/d;G’ FILE #輸出結果中間加空行 ?sed 'n;d' FILE #打印奇數行 ?sed -n '1!G;h;$p' FILE #倒敘排列
1、刪除centos7系統/etc/grub2.cfg文件中所有以空白開頭的行行首的空白字符 sed 's/^\([[:space:]]\+\)\([^[:space:]]\+\)/\2/g' /etc/grub2.cfg ? 2、刪除/etc/fstab文件中所有以#開頭,后面至少跟一個空白字符的行的行首的#和空白字符 sed 's/^\(#[[:space:]]\+\)\([^[:space:]]\+\)/\2/g' /etc/fstab ? 3、在centos6系統/root/install.log每一行行首增加#號 sed 's/.*/#&/g' /root/install.log ? 4、在/etc/fstab文件中不以#開頭的行的行首增加#號 sed 's/^[^#].*/#&/g' /etc/fstab ? 5、處理/etc/fstab路徑,使用sed命令取出其目錄名和基名 echo /etc/fstab|sed 's@\(^[/].*[/]\)\([^/]\+[/]\?\)@\1@g' echo /etc/fstab|sed 's@\(^[/].*[/]\)\([^/]\+[/]\?\)@\2@g' ? 6、利用sed 取出ifconfig命令中本機的v4地址 ifconfig eth0|sed -n '2p'|sed 's/\(.*ddr:\)\(.*\)\( Bcast.*\)/\2/g' ifconfig eth0|sed -n '2p'|sed 's/.*ddr://g'|sed 's/ Bca.*//g' ? 7、統計centos安裝光盤中Package目錄下的所有rpm文件的以.分隔倒數第二個字段的重復次數 ls |sed -r 's/(.*[.])([^.]+)([.][^.]+)/\2/g' ? 8、統計/etc/init.d/functions文件中每個單詞的出現次數,并排序(用grep和sed兩種方法分別實現) sed 's/[[:punct:]]/ /g' /etc/init.d/functions |tr '\t' ' '|tr ' ' '\n'|sed '/^$/d'|sort|uniq -c|sort -nr ? 9、將文本文件的n和n+1行合并為一行,n為奇數行 sed 'N;s/\n/\t /g' FILE
awk
awk變量,awk格式化,awk操作符,awk條件判斷,awk循環,awk數組,awk函數,調用系統命令
報告生成器,格式化文本輸出
awk相較于sed常常作用于整行的處理,awk比較傾向于一行當中分成數個字段來處理。awk相當適合處理小型的數據。在awk語法中行row,也可以稱為記錄record;列column,也可以稱為字段fields、域area、屬性Attributes。基本語法: awk [option] ‘program’ var=value file… awk [option] -f progarmfile var=value file… awk [option] ‘BEGIN{action;…}pattern{action;…}END{action;…}’file
program通常是被單引號或雙引號中,一般用單引號。默認的字段分隔符為“空格鍵”或“【tab】鍵”選項 -F:指明輸入時用到的字段分隔符 -v 進入變量模式 可以進行變量的賦值及調用(調用不需要加$符) 基本格式:awk [options]’program’file…program:pattern{action statements;…}pattern和action pattern部分決定動作語句何時觸發及觸發事件 BEGIN,END action statements對數據進行處理,放在{}內指明 print,printf分隔符、域和記錄
awk執行時,由分隔符分隔的字段(域)標記$1,$2..$n稱為域標識。$0為所有域,和shell中變量$符含義不同,如果省略action,則默認執行print $0操作。
示例: awk '{print "hello,awk"}' awk -F: '{print}' /etc/passwd awk -F: '{print "root" }' /etc/passwd awk -F: '{print $1}' /etc/passwd awk -F: '{print $0}' /etc/passwd awk -F: '{print $1" \t" $3}' /etc/passwd ?
awk變量:內置和自定義變量
FS(field separate):輸入字段分隔符,默認為空白字符 awk -v FS=':' '{print $1,FS,$3}' /etc/passwd awk -F: '{print $1,$3,$7}' /etc/passwd OFS:輸出字段分隔符,默認為空白字符 awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd RS(record separate):輸入記錄分隔符,指定輸入時的換行符 awk -v RS='' '{print}' /etc/passwd ORS:輸出記錄分隔符,輸出時用指定符號代替換行符 awk -v RS='' -v ORS='###' '{print}' /etc/passwd NF(number field):每一行($0)擁有的字段總數 awk -F: '{print NF}' /etc/passwd awk -F: '{print $(NF-1)} /etc/passwd NR:目前awk所處理的是第幾行的數據,即記錄號 awk '{print NR}' /etc/fstab;awk END'{print NR}' /etc/passwd FNR(filename number record):各文件分別計數,記錄號 awk '{print FNR}' /etc/fstab /etc/inittab FILENAME:當前文件名 awk '{print FILENAME}' /etc/fstab ARGC:命令行參數的個數 awk '{print ARGC}' /etc/fstab /etc/inittab ARGV:數組,保存的是命令行所給定的各參數 awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/inittab awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/inittab
示例: awk -v test='hello gawk' '{print test}' awk -v test='hello gawk' 'BEGIN{print test}' awk 'BEGIN{test="hello,gawk";print test}' awk -F: '{sex= "male" ;print $1,sex,age;age=18}' /etc/passwd
printf命令
格式化輸出:printf “FORMAT”,item1,item2 …
(1)必須指定FORMAT
(2)不會自動換行,需要顯示給出換行控制符
(3)FORMAT中需要分別為后面的每個item指定格式符
格式符:
? %c:顯示字符的ASCII碼
? %d,%i:顯示十進制數
? %e,%E顯示科學記數法數值
? %f:顯示為浮點數
? %g,%G:以科學記數法或浮點形式顯示數值
? %s:顯示字符串
? %u:無符號整數
? %%:顯示%自身
修飾符:
# [.#]:第一個數字控制顯示的寬度;第二個#表示小數點后精度,%3.1f -:左對齊(默認右對齊)%-15s +:顯示數值的正負符號%+d
printf示例:
awk -F: '{printf "$s",$1}' /etc/passwd awk -F: '{printf "%s\n,$1}' /etc/passwd awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd awk -F: '{printf "Username:%s\n",$1}' /etc/passwd awk -F: '{printf "Username:%s,UID:%d\n",$1,$3}' /etc/passwd awk -F: '{printf "Username:%15s,UID:%d\n",$1,$3}' /etc/passwd awk -F: '{printf "Username:%-15s,UID:%d\n",$1,$3}' /etc/passwd
? 操作符
? 算術操作符:
? x+y,x-y, x*y, x/y, x^y, x%y
? -x:轉換為負數
? +x:轉換為數值
? 賦值操作符:
? =,+=,-=,*=,/=,%=,^ =
? ++,–
? 下面兩語句有何不同
awk ‘BEGIN{i=0;print ++i,i}’
awk ‘BEGIN{i=0;print i++,i}’
? 比較操作符:
? == , != , > , >= , < , <=
? 模式匹配符:
~左邊是否和右邊匹配含!~:是否不匹配
? ? ? 示例: ? ? ? awk -F: '$0 ~ /root/{$1} ' ? /etc/passwd ? ? ? awk '$0 ~ "^root"' /etc/passwd ? ? ? awk '$0 !~ /root/ ' ? /etc/passwd ? ? ? awk -F: '$3==0' /etc/passwd
? 邏輯 操作符:與&&,或||,非!
? ? ? 示例: ? ? ? awk –F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd ? ? ? awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd ? ? ? awk -F: ‘!($3==0) {print $1}' /etc/passwd ? ? ? awk -F: ‘!($3>=500) {print $3}’ /etc/passwd
? 函數調用:
function_name(argu1,argu2,…)
? 條件表達式(三目表達式)
selector?if-true-expression:if-false-expression 示例: awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
? awk PATTERN
? PATTERN:根據pattern 條件,過濾匹配的行,再做處理
? (1)如果未指定:空模式,匹配每一行
? (2)/regular expression/:僅處理能夠模式匹配到的行,需要用/ /擴起來
(3)relational expression:關系表達式,結果為“真”才會被處理
? 真:結果為非0值,非空字符串
? 假:結果為空字符串或0值
? ? ? 示例: ? ? ? awk -F: 'i=1;j=1{print i,j}' /etc/passwd ? ? ? awk ‘!0’ /etc/passwd ; awk ‘!1’ /etc/passwd ? ? ? 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:行范圍
? startline,endline:/pat1/,/pat2/不支持直接給出數字格式
? ? ? ? ? ? awk -F: '/^root\>/,/^nobody\>/{print $1}' /etc/passwd ? ? ? ? ? ? awk -F: ‘(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
? (5)BEGIN/END模式
? BEGIN/END{}:僅在開始處理文件中的文本之前執行一次
? END{}:僅在文本處理完成之后執行一次
示例: awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd awk -F : '{print "USER USERID“;print $1":"$3} END{print "end file"}' /etc/passwd awk -F: 'BEGIN{print " USER UID \n--------------- "}{print $1,$3}' /etc/passwd awk -F: 'BEGIN{print " USER UID \n--------------- "}{print $1,$3}'END{print "=============="} /etc/passwd seq 10 |awk ‘i=0’ #等同于seq 10 |awk 'i=0{print $0},0為假,所以輸出結果為空 seq 10 |awk ‘i=1’ #輸出結果為1到10 seq 10 | awk 'i=!i‘ #打印奇數行 seq 10 | awk '{i=!i;print i}‘ #打印1010101010 seq 10 | awk ‘!(i=!i)’ #打印偶數行 seq 10 |awk -v i=1 'i=!i' #打印偶數行
awk action
常用的action分類
(1)Expressions:算術,比較表達式等
(2)Control statements:if ,while等
(3)compound statements:組合語句
(4)input statements
(5)output statements:print等
awk控制語句if-else
語法: if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else{statement3}
使用場景:對awk取得的整行或某個字段做條件判斷
示例: awk -F:'{if($3>=1000)print $1,$3}' /etc/passwd awk -F:'{if($NF=="/bin/bash")print $1}' /etc/passwd awk -F:'{if(NF>5)print$0}' /etc/fstab awk -F:'{if($3>=1000){print"Common user:%s\n,$1}else{print"root or Sysuer:%s\n".$1}}' /etc/passwd awk -F:'{if{$3>=1000}printf"Common user:%s\n",$1;else printf"root or Sysuser:%s\n,$1}' /etc/passwd df -h |awk -F% '/^\/dev/{print$1}'|awk '$NF>=80{print $1,$5}' awk 'BEGIN{test=100;if(test>90){print"very good"}else if(test>60){print "good"}else{print"no pass"}}'
awk控制語句
while循環
語法:while(condition){statement;…}
條件“真”,進入循環;條件“假”,退出循環
使用場景:
對一行內的多個字段逐一類似處理時使用
對數組中的各元素逐一處理時使用
示例: awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=10){print $i,length($i)};}}' /etc/grub2.cfg
do-while循環
語法:do {statement;…}while(condition)
意義:無論真假,至少執行一次循環體
示例: awk'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100);print total}'
for循環
語法:for(expr1;expr2;expr3){statement;…}
常見用法:
for(variable assignment;condition;iteration process)
{for-body}
特殊用法:能夠遍歷數組中的元素
語法:for(var in array){for-body}
示例: awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg
awk控制語句
switch語句
語法:switch(expression){case VALUE1 or /REGEXP/:statement1;case VALUE2 or /REGEXP2/:statemet2/:statement2;…;default:statement}
break和continue
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}' awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}
awk控制語句
break[n]
continue[n]
Next:
提前結束對本行處理而直接進入下一行處理(awk自身循環)
awk -F:'{if($3%2!=0)next;print $1,$3}' /etc/passwd
awk數組
關聯數組:array[index-expression]
Index-expression:
cat > test1.txt 1,beijing 1,beijing 2,beijing 3,tianjin 5,tianjin 15,shanghai # awk -F"," '{ary[$2]+=$1} END{for(key in ary)print ary[key]","key}' 4,beijing 8,tianjing 15,shanghai
(1):可使用任意字符串;字符串要使用雙括號括起來
(2):如果某數組元素事先不存在,在使用時,awk會自動創建次元素,并將其值初始化為“空串”
若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷
示例: weekdays[ "mon" ]="Monday" awk 'BEGIN{weekdays["mon"]="Mondya";weekdays["tue"]="Tuesday";print weekdays["mon"]}' awk '!arr[$0]++ dupfile
若要遍歷數組中的每個元素,要使用for循環
for(var in array){for-body}
注意:var會遍歷array的每個索引
示例: awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesdya";for(i in weekdays){print weekdays[i]}}' 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]}}' /var/log/httpd/access_log
awk函數
數值處理:
rand():返回0和1之間一個隨機數
Awk ‘BEGIN{srand();for(i=1;i<=10;i++)print int(rand()*100)}’
字符串處理: length([s]):返回指定字符串的長度
sub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,并將第一個匹配的內容替換為s
echo “2008:08:08 08:08:08” |awk ‘sub(/:/, “-,$1”)’
gsub(r,s,[t]):對字符串進行搜索r表示的模式匹配的內容,并全部替換為s所表示的內容
echo “2008:08:08 08:08:08” |awk ‘gsub(/:/, “-“$0)’
split(s,starry,[r]):以r為分隔符,切割字符串s,并將切割后的結果保存至array所表示的數組中,第一個索引值為1,第二個索引值為2,…
netstat -tan |awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count)}'
awk函數
自定義函數
格式: function name(parameter, parameter,…){
statements
return expression
}
示例: cat fun.awk function max(v1,v2){ ? v1>v2?var=v1:var=v2 ? return var } BEGIN{a=3;b=2;print max(a,b)} awk -f fun.awk
awk中調用shell命令
system命令
空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk的變量外其它一律用“”引用起來。
awk BEGIN'{system(“hostname”)}’
awk ‘BEGIN{score=100;system(“echo your score is” score)}’
awk腳本
將awk程序寫成腳本,直接調用或執行
示例: cat f1.awk {if($3>=1000)print $1,$3} awk -F:-f f1.awk /etc/passwd ? cat f2.awk # f2.awk -f #this is a awk script {if($3>=1000)print $1,$3} chmod +x f2.awk f2.awk -F: /etc/passwd
向awk腳本傳遞參數
格式:
awkfile var=value var2=value2…inputfile
注意:在BEGIN過程中不可用。直到首行輸入完成以后,變量才可用??梢酝ㄟ^-v參數,讓awk在執行BEGIN之前得到變量的值。命令行只能夠每一個指定的變量都需要一個-v參數
示例: cat test.awk #!/bin/awk -f {if($3 >=min && $3<=max)print $1,$3} chmod +x test.awk test.awk -F: min=100 max=200 /etc/passwd
統計row中某個字段出現的次數
1、統計本機被訪問次數
Awk ‘/^[0-9]/{ip{$1}++}END{for(i in ip){print i ,ip[i]}}’ /var/log/httpd/access_log
2、如果超過訪問超過1000次就視為攻擊,放入防火墻中
for i in `awk
iptables -A INPUT -s 192.168.30.6 -j REJECT
3、抽取連接本機ip的前十位。
4、統計/etc/rc.sysinit某個文檔里面某個單詞出現的次數,默認以空格位分隔符
思路:逐行統計,再匯總
5、某班考試成績表如下:
姓名 | 性別 | 成績 |
---|---|---|
mage | male | 100 |
zhangsir | male | 99 |
bai | female | 90 |
li | female | 100 |
根據成績表,統計男生平均成績和女生平均成績
#cat score.txt mage 100 m zhangsir 100 m bai 90 f li 100 f ? 方法1: # awk '{if($NF=="m"){sum_m+=$2;num_m++}else{sum_f+=$2;num_f++}}END{print "male:%.2f\nfemale:%.2f\n",sum_m/num_m,sum_f/num_f}' score.txt male:99.50 female:95.00 方法2:數組 awk '{num[$NF]++;sum[$NF]+=$2}END{for(sex in num)printf "%s:%.2f\n",sex,sum[sex]/num[sex]}' score.txt m:99.50 f:95.00
本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/98029