Linux文本三劍客總結

Linux文本處理三劍客

grep

文本過濾(模式:pattern)工具 grep, egrep, fgrep(不支持正則表達式搜索)html

grepnode

 grep: Global search REgular expression and Print out the line
 做用:文本搜索工具,根據用戶指定的「模式」對目標文本逐行進行匹配檢查;打印匹配到的行
 模式:由正則表達式字符及文本字符所編寫的過濾條件
 grep [OPTIONS] PATTERN [FILE...]
 grep root /etc/passwd
 grep "$USER" /etc/passwd
 grep '$USER' /etc/passwd
 grep `whoami` /etc/passwd

grep命令選項linux

 --color=auto: 對匹配到的文本着色顯示
 -m # 匹配#次後中止
 -v 顯示不被pattern匹配到的行
 -i 忽略字符大小寫
 -n 顯示匹配的行號
 -c 統計匹配的行數
 -o 僅顯示匹配到的字符串
 -q 靜默模式,不輸出任何信息
 -A # after, 後#行
 -B # before, 前#行
 -C # context, 先後各#行
 -e 實現多個選項間的邏輯or關係
 grep –e ‘cat -e ‘dog’ file
 -w 匹配整個單詞
 -E 使用ERE
 -F 至關於fgrep,不支持正則表達式
 -f file 根據模式文件處理

正則表達式

 REGEXP: Regular Expressions,由一類特殊字符及文本字符所編寫的模式,其中有些字符(元字符)不表示字符字面意義,而表示控制或通配的功能
 程序支持:grep,sed,awk,vim, less,nginx,varnish等
 分兩類:
 基本正則表達式:BRE
 擴展正則表達式:ERE
 grep -E, egrep
 正則表達式引擎:
 採用不一樣算法,檢查處理正則表達式的軟件模塊
 PCRE(Perl Compatible Regular Expressions)
 元字符分類:字符匹配、匹配次數、位置錨定、分組
 man 7 regex

基本正則表達式元字符 字符匹配:nginx

 . 匹配任意單個字符
 [] 匹配指定範圍內的任意單個字符,示例:[wang] [0-9] [a-z] [a-zA-Z]
 [^] 匹配指定範圍外的任意單個字符
 [:alnum:] 字母和數字
 [:alpha:] 表明任何英文大小寫字符,亦即 A-Z, a-z
 [:lower:] 小寫字母 [:upper:] 大寫字母
 [:blank:] 空白字符(空格和製表符)
 [:space:] 水平和垂直的空白字符(比[:blank:]包含的範圍廣)
 [:cntrl:] 不可打印的控制字符(退格、刪除、警鈴...
 [:digit:] 十進制數字 [:xdigit:]十六進制數字
 [:graph:] 可打印的非空白字符
 [:print:] 可打印字符
 [:punct:] 標點符號
 匹配次數:用在要指定次數的字符後面,用於指定前面的字符要出現的次數
 匹配前面的字符任意次,包括0次
 貪婪模式:儘量長的匹配
 .* 任意長度的任意字符
 \? 匹配其前面的字符0或1次
 \+ 匹配其前面的字符至少1次
 \{n\} 匹配前面的字符n次
 \{m,n\} 匹配前面的字符至少m次,至多n次
 \{,n\} 匹配前面的字符至多n次
 \{n,\} 匹配前面的字符至少n次

位置錨定:定位出現的位置git

 ^ 行首錨定,用於模式的最左側
 $ 行尾錨定,用於模式的最右側
 ^PATTERN$ 用於模式匹配整行
 ^$ 空行
 ^[[:space:]]*$ 空白行
 \< \b 詞首錨定,用於單詞模式的左側
 \> \b 詞尾錨定,用於單詞模式的右側
 \<PATTERN\> 匹配整個單詞
 分組:\(\) 將一個或多個字符捆綁在一塊兒,看成一個總體處理,如:\(root\)\+
 分組括號中的模式匹配到的內容會被正則表達式引擎記錄於內部的變量中,這些變量的命名方式爲: \1, \2, \3, ...
 \1 表示從左側起第一個左括號以及與之匹配右括號之間的模式所匹配到的字符
 示例: \(string1\(string2\)\)
 \1 :string1\(string2\)
 \2 :string2
 後向引用:引用前面的分組括號中的模式所匹配字符,而非模式自己
 或者:\|
 示例:a\|b a或b
 C\|cat C或cat
 \(C\|c\)at Cat或cat

 

 

 

 

 

 

 

練習題:

一、顯示/proc/meminfo文件中以大小s開頭的行(要求:使用兩種方法)web

 [root@shell ~]# grep -in '^s' /proc/meminfo 
 [root@shell ~]# cat /proc/meminfo |grep "^[sS]"
 cat /proc/meminfo | grep '^[sS]'  # 匹配開頭[sS]任意單個字符
 cat /proc/meminfo | grep '^[s\|S]'  # 匹配開頭s或者S
 grep '^s\|^S' /proc/meminfo   # 匹配開頭s或者開頭S
 grep -i '^s' /proc/meminfo  # 匹配開頭s忽略大小寫

二、顯示/etc/passwd文件中不以/bin/bash結尾的行正則表達式

 [root@shell ~]#cat /etc/passwd |grep -nv 「/bin/bash$」

三、顯示用戶rpc默認的shell程序算法

 cat /etc/passwd | grep -w '^root' | grep -o '[^/]\+$'

四、找出/etc/passwd中的兩位或三位數shell

 grep "\b[0-9]\{2,3\}\b" /etc/passwd  # \b 詞首錨定,\b 詞尾錨定
 grep '\<[0-9]\{2,3\}\>' /etc/passwd  # \< 詞首錨定,\> 詞尾錨定
 grep -w '[0-9]\{2,3\}' /etc/passwd
 egrep -w '[0-9]{2,3}' /etc/passwd

五、顯示CentOS7的/etc/grub2.cfg文件中,至少以一個空白字符開頭的且後面有非空白字符的行express

 grep '^[[:space:]]\+[^[:graph:]]' /etc/grub2.cfg
 egrep '^[[:space:]]+[^[:graph:]]' /etc/grub2.cfg

六、找出「netstat -tan」命令結果中以LISTEN後跟任意多個空白字符結尾的行

 netstat -tan | grep 'LISTEN[[:space:]]*$'

七、顯示CentOS7上全部UID小於1000之內的用戶名和UID

 cut -d: -f 1,3 /etc/passwd | grep '\<[0-9]\{0,3\}\>'  # 匹配任意數字至少0個字符,至多3個字符
 cut -d: -f 1,3 /etc/passwd | grep '\b[0-9]\{0,3\}\b'
 cut -d: -f 1,3 /etc/passwd | grep -w '[0-9]\{0,3\}'
 cut -d: -f 1,3 /etc/passwd | egrep -w '[0-9]{0,3}'
 cut -d: -f 1,3 /etc/passwd | tr : ' ' | awk '{if($2<1000)print $1,$2}'| tr ' ' :

八、添加用戶bash、testbash、basher、sh、nologin(其shell爲/sbin/nologin),找出/etc/passwd用戶名和shell同名的行

useradd bash && useradd testbash && useradd basher && useradd sh && useradd -s /sbin/nologin nologin
 cat /etc/passwd | grep '\(^[a-zA-Z0-9]\+\>\).*\<\1$'
 cat /etc/passwd | egrep '(^[[:alnum:]]+\>).*\<\1$'  

 # 匹配以任意數字或字母開頭的單詞至少一次,放入內置變量 \1,再匹配任意字符任意次直到結尾前一個單詞是 \1

九、利用df和grep,取出磁盤各分區利用率,並從大到小排序

 df | grep ^/dev | grep -o '[0-9]\{1,\}%'|sort -nr  # -o 只顯示匹配的字符串
 df | grep ^/dev | egrep -o '[0-9]{1,}%'|sort -nr  # {1,} 匹配前一個字符至少1次

egrep

egrep及擴展的正則表達式

egrep = grep -E egrep [OPTIONS] PATTERN [FILE...] 擴展正則表達式的元字符: 字符匹配: . 任意單個字符 [] 指定範圍的字符 [^] 不在指定範圍的字符

擴展正則表達式

 次數匹配:
 .匹配前面字符任意次
 ? 0或1次
 + 1次或屢次
 {m} 匹配m次
 {m,n} 至少m,至多n次

擴展正則表達式 位置錨定:

 ^ 行首
 $ 行尾
 \<, \b 語首
 \>, \b 語尾
 分組:
 ()
 後向引用:\1, \2, ...
 或者:
 a|b a或b
 C|cat C或cat
 (C|c)at Cat或cat

練習題:

一、顯示三個用戶root、mage、wang的UID和默認shell

 cut -d: -f1,3,7 /etc/passwd | grep -w '^\(root\|mage\|wang\)'
 cut -d: -f1,3,7 /etc/passwd | egrep -w '^(root|mage|wang)'

二、找出/etc/rc.d/init.d/functions文件中行首爲某單詞(包括下劃線)後面跟一個小括號的行

 egrep -o '^.*\(\)' /etc/rc.d/init.d/functions
 grep -o '^[a-zA-Z0-9_].*()' /etc/rc.d/init.d/functions
 grep -o '^[[:alnum:]_].*()' /etc/rc.d/init.d/functions

三、使用egrep取出/etc/rc.d/init.d/functions中其基名

 echo /etc/rc.d/init.d/functions | egrep -o '[^/]+$'
 # 從最後一個字符開始向前匹配,排除/至少一次後中止
 echo /etc/rc.d/init.d/functions | egrep -ow '[[:alnum:]]+$'

 # 從最後一個字符開始向前匹配,匹配到任意字母或數字組成的單詞至少一次後中止,基名不能有特殊字符

四、使用egrep取出上面路徑的目錄名

 echo /etc/rc.d/init.d/functions | egrep -o  '.*/\<'
 root@shell ~]# echo /etc/rc.d/init.d/functions | egrep -o  '.*/\b'
 /etc/rc.d/init.d/
 [root@shell ~]# echo /etc/rc.d/init.d/functions | grep -o  '.*/\+\b'
 /etc/rc.d/init.d/

五、統計last命令中以root登陸的每一個主機IP地址登陸次數

 last | grep '^root' | awk '{print $1,$3}'| grep -v '[a-z]$'| sort | uniq -c
 # 篩選root登錄;篩選只顯示用戶和主機IP;排除沒有主機IP的行(不顯示以任意字母結尾的行);排序;統計
last | grep ^root | egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}" | sort | uniq -c
 # 篩選root登錄;篩選只顯示主機IP;排序;統計

六、利用擴展正則表達式分別表示0-九、10-9九、100-19九、200-24九、250-255

 echo {1..255} | egrep -wo '[0-9]' | tr "\n" " " ; echo
 echo {1..255} | egrep -wo '[1-9][0-9]' | tr "\n" " " ; echo
 echo {1..255} | egrep -wo '1[0-9]{2}' | tr "\n" " " ; echo
 echo {1..255} | egrep -wo '2[0-4][0-9]' | tr "\n" " " ; echo
 echo {1..255} | egrep -wo '25[0-5]' | tr "\n" " " ; echo

七、顯示ifconfig命令結果中全部IPv4地址

 ifconfig | egrep -o "\<(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4]0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"

八、將此字符串:welcome to magedu linux 中的每一個字符去重並排序,重複次數多的排到前面

 echo "welcome to magedu linux" | tr -d " " | egrep -o "." | sort | uniq -c | sort -nr

 # 刪除空格;拆分字符到每行(只顯示匹配到的任意字符的行);排序;去重;按第一行數字降序排序

sed

stream editor,文本編輯工具

Stream EDitor, 行編輯器 sed是一種流編輯器,它一次處理一行內容。處理時,把當前處理的行存儲在臨時緩衝區中,稱爲「模式空間」(pattern space),接着用sed命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往屏幕。而後讀入下行,執行下一個循環。若是沒有使諸如‘D’的特殊命令,那會在兩個循環之間清空模式空間,但不會清空保留空間。這樣不斷重複,直到文件末尾。文件內容並無改變,除非你使用重定向存儲輸出。 功能:主要用來自動編輯一個或多個文件,簡化對文件的反覆操做,編寫轉換程序等 參考: http://www.gnu.org/software/sed/manual/sed.html

sed工具

用法:

 sed [option]... 'script' inputfile...
 經常使用選項:
 -n 不輸出模式空間內容到屏幕,即不自動打印
 -e 多點編輯
 -f /PATH/SCRIPT_FILE 從指定文件中讀取編輯腳本
 -r 支持使用擴展正則表達式
 -i.bak 備份文件並原處編輯
 script:
 '地址命令'

地址定界:

 (1) 不給地址:對全文進行處理
 (2) 單地址:
 #:指定的行,$:最後一行
 /pattern/:被此處模式所可以匹配到的每一行
 (3) 地址範圍:
 #,#
 #,+#
 /pat1/,/pat2/
 #,/pat1/
 (4) ~:步進
 1~2 奇數行
 2~2 偶數行

編輯命令:

 d 刪除模式空間匹配的行,並當即啓用下一輪循環
 p 打印當前模式空間內容,追加到默認輸出以後
 a [\]text 在指定行後面追加文本,支持使用\n實現多行追加
 i [\]text 在行前面插入文本
 c [\]text 替換行爲單行或多行文本
 w /path/file 保存模式匹配的行至指定文件
 r /path/file 讀取指定文件的文本至模式空間中匹配到的行後
 = 爲模式空間中的行打印行號
 ! 模式空間中匹配行取反處理

 s/// 查找替換,支持使用其它分隔符,s@@@,s###
 替換標記:
 g 行內全局替換
 p 顯示替換成功的行
 w /PATH/FILE 將替換成功的行保存至文件中

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 [options] 'script' inputfile...
 sed [options] -f scriptfile file(s)
     -e<script>,--expression=<script>    以指定的 script 來處理輸入的文件,用於順序執行多條命令
     -f<script 文件>,--file=<script 文件> 以指定的 script 文件來處理輸入的文件
     -n,--quiet,——silent                  取消自動打印模式空間
     -i[SUFFIX], --in-place[=SUFFIX]      直接編輯文件(若是提供後綴,則進行備份)
     -r                                   使用擴展正則表達式
 sed元字符集
 ^         匹配行開始,如:/^sed/匹配全部以sed開頭的行。
 $         匹配行結束,如:/sed$/匹配全部以sed結尾的行。
 .         匹配一個非換行符的任意字符,如:/s.d/匹配s後接一個任意字符,最後是d。
 *         匹配0個或多個字符,如:/*sed/匹配全部模板是一個或多個空格後緊跟sed的行。
 []        匹配一個指定範圍內的字符,如/[ss]ed/匹配sed和Sed。  
 [^]       匹配一個不在指定範圍內的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一個字母開頭,緊跟ed的行。
 \(..\)    匹配子串,保存匹配的字符,如s/\(love\)able/\1rs,loveable被替換成lovers。
 &         保存搜索字符用來替換其餘字符,如s/love/**&**/,love這成**love**。
 \<        匹配單詞的開始,如:/\<love/匹配包含以love開頭的單詞的行。
 \>        匹配單詞的結束,如/love\>/匹配包含以love結尾的單詞的行。
 x\{m\}    重複字符x,m次,如:/0\{5\}/匹配包含5個0的行。
 x\{m,\}   重複字符x,至少m次,如:/0\{5,\}/匹配至少有5個0的行。
 x\{m,n\}  重複字符x,至少m次,很少於n次,如:/0\{5,10\}/匹配5~10個0的行。
 ​
 sed地址定界:默認對全文進行處理
 #              指定行
 $              最後一行
 /pattern/      被 pattern 匹配到的每一行
 #,#            區間
 #,+#           區間 +#=#+1
 /pat1/,/pat2/
 #,/pat1/
 first~step     步進(stepping) 先定位 first 所在行,而後每通過step行再定位一次
 1~2            奇數行
 2~2            偶數行
 first,~N       從 first 所在的行至日後第一個能夠被N整除的行
 ​
 GNU擴展的sed,支持特殊序列(special sequence),它由一個反斜線和一個字母組成:
 \L:將replacement替換成小寫直到遇到\U或者\E。
 \l:將下一個字符替換成小寫。
 \U:將replacement替換成大寫直到遇到\L或者\E。
 \u:將下一個字符替換成大寫。
 \E:中止\U或者\L帶來的大小寫轉換功能。
 Examples:
 sed '2p' /etc/passwd                    打印文件內容,並重復打印文件第2行
 sed -n '2p' /etc/passwd                 只打印文件第2行
 sed -n '1,4p' /etc/passwd               只打印文件第1到4行
 sed -n '/root/p' /etc/passwd            只打印文件匹配 root 的行
 sed -n '2,/root/p' /etc/passwd          只打印文件從第2行開始到匹配 root 的行
 sed -n '/^$/=' file                     顯示空行行號(只打印文件匹配 ^$ 的行及其行號)
 sed -n -e '/^$/p' -e '/^$/=' file       只打印文件空行和空行及其行號
 sed '/root/a superman' /etc/passwd      匹配 root 的行後追加一行 superman
 sed '/root/i superman' /etc/passwd      匹配 root 的行前追加一行 superman
 sed '/root/c superman' /etc/passwd      用 superman 代替匹配 root 的行
 nl /etc/passwd | sed '2a tea'           文件第2行後追加一行 tea
 sed -n 's/root/&superman/p' /etc/passwd 只打印匹配 root 單詞後追加 superman 單詞的行
 sed -n 's/root/superman&/p' /etc/passwd 只打印匹配 root 單詞前追加 superman 單詞的行
 sed -i.bak 's/dog/cat/g' file           備份.bak 後,在原文件中替換並保存
 sed -i.bak 's/dog/cat/g' file           備份.bak 後,在原文件中替換並保存
 ​
 已匹配字符串標記&
 sed 's/\w\+/[&]/g' file      #  \w\+ 匹配每個單詞
 替換操做:s命令
 sed 's/book/books/' file
 sed -n 's/test/TEST/p' file  # -n 抑制自動打印原文本,p 打印處理後的行。只打印發生替換的行
 刪除操做:d命令
 sed '/^$/d' file     刪除空白行
 sed '/^test/d' file  刪除文件中全部開頭是test的行
 sed '2d' file        刪除文件的第2行
 sed '$d' file        刪除文件最後一行
 sed '2,$d' file      刪除文件的第2行到末尾全部行
 地址定界:,(逗號)
 sed -n '/test/,/check/p' file     全部在模板test和check所肯定的範圍內的行都被打印
 sed -n '5,/^test/p' file          打印從第5行開始到第一個包含以test開始的行之間的全部行:
 sed '/test/,/west/s/$/aaa/' file  模板test和west之間的行,每行的末尾用字符串aaa替換
 模式空間:
 sed '1!G;h;$!d' FILE ; sed -n '1!G;h;$p' FILE   倒序輸出(模擬tac)
 sed 'N;D' FILE ; sed '$!d' FILE         輸出文件最後一行
 sed '$!N;$!D' FILE                      輸出文件最後2行
 sed 'G' FILE                            給每行結尾添加一行空行
 sed 'g' FILE                            將文件所有行替換成空行
 sed 'N;s/\n//g' FILE                    將文件的n和n+1行合併爲一行,n爲奇數行
 sed ':a;N;$!ba;s/\n//g'                 將文件全部行合爲一行
 sed '/^$/d;G' FILE                      刪除空白行後,給每行結尾添加一行空行
 sed 'n;d' FILE                          刪除偶數行
 sed -n 'p;n' test.txt  #奇數行
 sed -n 'n;p' test.txt  #偶數行
 sed '/test/{ n; s/aa/bb/; }' file 匹配test,移動到下一行,替換aa爲bb,並打印該行
 ​
 打印匹配字符串的下一行
 grep -A 1 SCC URFILE
 sed -n '/SCC/{n;p}' URFILE
 awk '/SCC/{getline; print}' URFILE
 sed ':a;N;$!ba;s/\n//g' ; sed ':a;$!N;s/\n//g;ta'  將文件全部行合爲一行
 :a         # 創建分支標記
 N          # 讀取下一行追加至模式空間
 $!ba       # 分支到腳本中帶有標記的地方
 s/\n//g    # 替換\n爲空

練習題

一、刪除centos7系統/etc/grub2.cfg文件中全部以空白開頭的行行首的空白字符

 sed 's#[[:space:]]*##g' /etc/grub2.cfg

二、刪除/etc/fstab文件中全部以#開頭,後面至少跟一個空白字符的行的行首的#和空白字符

 sed -r s/^#[[:space:]*// /etc/fstab

三、在centos6系統/root/install.log每一行行首增長#號

 sed s/^Installing/#Installing/g /root/install.log

四、在/etc/fstab文件中不以#開頭的行的行首增長#號

 sed -r "s/(^[^#])*/#\1/" /etc/fstab

五、處理/etc/fstab路徑,使用sed命令取出其目錄名和基名

 基名:echo /etc/fstab | sed -r "s#^(/.*/)([^/]+/?)#\2#"
 目錄名:echo /etc/fstab | sed -r "s#^(/.*/)([^/]+/?)#\1#g"

六、利用sed 取出ifconfig命令中本機的IPv4地址

 ifconfig ens33 |sed -n '2p' | sed -r "s/.*inet[[:space:]]*//" | sed -r "s/[[:space:]]*netmask.*//"

七、統計centos安裝光盤中Package目錄下的全部rpm文件的以.分隔倒數第二個字段的重複次數

 ls /run/media/root/CentOS\ 7\ x86_64/Packages/ | grep -v "TBL" |sed -r "s#(.*\.([^.]+).rpm$)#\2#"

八、統計/etc/init.d/functions文件中每一個單詞的出現次數,並排序(用grep和sed兩種方法分別實現)

 grep方法:cat /etc/init.d/functions |grep -io "\<[[:alpha:]]*\>" |sort -rn |uniq -c |sort -n
 sed方法:sed "s/[^[:alpha:]]/\n/g" /etc/init.d/functions" | sort -rn | uniq -c |sort -n

九、將文本文件的n和n+1行合併爲一行,n爲奇數行

 sed 'N;s/\n//'

awk

Linux上的實現gawk,文本報告生成器

awk介紹 awk:Aho, Weinberger, Kernighan,報告生成器,格式化文本輸出 有多種版本:New awk(nawk),GNU awk( gawk) gawk:模式掃描和處理語言 基本用法: awk [options] 'program' var=value file… awk [options] -f programfile var=value file… awk [options] 'BEGIN{action;… }pattern{action;… }END{action;… }' file ... awk 程序可由:BEGIN語句塊、可以使用模式匹配的通用語句塊、END語句塊,共3部分組成 program 一般是被放在單引號中 選項: -F 「分隔符」 指明輸入時用到的字段分隔符 -v var=value 變量賦值

awk語言

 基本格式: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工做原理

 第一步:執行BEGIN{action;… }語句塊中的語句
 第二步:從文件或標準輸入(stdin)讀取一行,而後執行pattern{ action;… }語句塊,它逐行掃描文件,從第一行到最後一行重複這個過程,直到文件所有被讀取完畢。
 第三步:當讀至輸入流末尾時,執行END{action;…}語句塊
 BEGIN語句塊在awk開始從輸入流中讀取行以前被執行,這是一個可選的語句塊,好比變量初始化、打印輸出表格的表頭等語句一般能夠寫在BEGIN語句塊中
 END語句塊在awk從輸入流中讀取完全部的行以後即被執行,好比打印全部行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊
 pattern語句塊中的通用命令是最重要的部分,也是可選的。若是沒有提供pattern語句塊,則默認執行{ print },即打印每個讀取到的行,awk讀取的每一行都會執行該語句塊

awk print格式:print item1, item2, ... 要點:

 (1) 逗號分隔符
 (2) 輸出item能夠字符串,也但是數值;當前記錄的字段、變量或awk的表達式
 (3) 如省略item,至關於print $0
 示例:
 awk '{print "hello,awk"}'
 awk –F: '{print}' /etc/passwd
 awk –F: ‘{print 「wang」}’ /etc/passwd
 awk –F: ‘{print $1}’ /etc/passwd
 awk –F: ‘{print $0}’ /etc/passwd
 awk –F: ‘{print $1」\t」$3}’ /etc/passwd
 grep 「^UUID」/etc/fstab | awk ‘{print $2,$4}’

awk變量 變量:內置和自定義變量

 FS:輸入字段分隔符,默認爲空白字符
 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:輸入記錄分隔符,指定輸入時的換行符
 awk -v RS=' ' ‘{print }’ /etc/passwd
 ORS:輸出記錄分隔符,輸出時用指定符號代替換行符
 awk -v RS=' ' -v ORS='###'‘{print }’ /etc/passwd
 NF:字段數量
 awk -F:‘{print NF}’ /etc/fstab 引用變量時,變量前不需加$
 awk -F:‘{print $(NF-1)}' /etc/passwd
 NR:記錄號
 awk ‘{print NR}’ /etc/fstab ; awk END‘{print NR}’ /etc/fstab

 FNR:各文件分別計數,記錄號
 awk '{print FNR}' /etc/fstab /etc/inittab
 FILENAME:當前文件名
 awk '{print FILENAME}’ /etc/fstab
 ARGC:命令行參數的個數
 awk '{print ARGC}’ /etc/fstab /etc/inittab
 awk ‘BEGIN {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
 自定義變量(區分字符大小寫)
 (1) -v var=value
 (2) 在program中直接定義
 示例:
 awk -v test='hello gawk' '{print test}' /etc/fstab
 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
 cat awkscript
 {print script,$1,$2}
 awk -F: -f awkscript script=「awk」 /etc/passwd
 printf命令
 格式化輸出:printf 「FORMAT」, item1, item2, ...
 (1) 必須指定FORMAT
 (2) 不會自動換行,須要顯式給出換行控制符,\n
 (3) FORMAT中須要分別爲後面每一個item指定格式符
 格式符:與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/{print $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

 條件表達式(三目表達式)
 selector?if-true-expression:if-false-expression
 •示例:
 awk -F: '{$3>=1000?usertype="Common User":usertype=" SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
 PATTERN:根據pattern條件,過濾匹配的行,再作處理
 (1)若是未指定:空模式,匹配每一行
 (2) /regular expression/:僅處理可以模式匹配到的行,須要用/ /括起來
 awk '/^UUID/{print $1}' /etc/fstab
 awk '!/^UUID/{print $1}' /etc/fstab
 (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

awk PATTERN

  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
 BEGIN/END模式
 BEGIN{}:僅在開始處理文件中的文本以前執行一次
 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=1'
 seq 10 | awk 'i=!i'
 seq 10 | awk '{i=!i;print i}'
 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控制語句

 { statements;… } 組合語句
 if(condition) {statements;…}
 if(condition) {statements;…} else {statements;…}
 while(conditon) {statments;…}
 do {statements;…} while(condition)
 for(expr1;expr2;expr3) {statements;…}
 break
 continue
 delete array[index]
 delete array
 exit

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 '{if(NF>5) print $0}' /etc/fstab
 awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %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」}}’

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)}; i++}}’ /etc/grub2.cfg
 [root@shell ~]# echo I am oldboy teacher welcome to oldboy training class|awk '{for(i=1;i<=NF;i++){if (length($i)<=6) {print $i}}}' 
 I
 am
 oldboy
 to
 oldboy
 class
 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
 性能比較
 time (awk 'BEGIN{ total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')
 time(total=0;for i in {1..10000};do total=$(($total+i));done;echo $total)
 time(for ((i=0;i<=10000;i++));do let total+=i;done;echo $total)
 time(seq –s 」+」 10000|bc)
 switch語句
 語法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}
 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}'

 break [n]
 continue [n]
 next:
提早結束對本行處理而直接進入下一行處理(awk自身循環)
 awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

awk數組 關聯數組:array[index-expression] index-expression:

 (1) 可以使用任意字符串;字符串要使用雙引號括起來
 (2) 若是某數組元素事先不存在,在引用時,awk會自動建立此元素,並將其值初始化爲「空串」
 (3) 若要判斷數組中是否存在某元素,要使用「index in array」格式進行遍歷
 示例:
 weekdays["mon"]="Monday"
 awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";
 print weekdays["mon"]}‘
 awk '!line[$0]++' dupfile
 awk '{!line[$0]++;print $0, line[$0]}' dupfile

 若要遍歷數組中的每一個元素,要使用for循環
 for(var in array) {for-body}
 注意:var會遍歷array的每一個索引
 示例: awk‘BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday"; 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

 數值處理:
 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)'
 echo "2008:08:08 08:08:08" | awk '{sub(/:/,"-",$1);print $0}'
 •gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並所有替換爲s所表示的內容
 echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
 echo "2008:08:08 08:08:08" | awk '{gsub(/:/,"-",$0);print $0}'
 •split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存至array所表示的數組中,第一個索引值爲1,第二個索引值爲2,…
 netstat -tn | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}
 END{for (i in count) {print i,count[i]}}’

 數值處理:
 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)'
 echo "2008:08:08 08:08:08" | awk '{sub(/:/,"-",$1);print $0}'
 •gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並所有替換爲s所表示的內容
 echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
 echo "2008:08:08 08:08:08" | awk '{gsub(/:/,"-",$0);print $0}'
 •split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存至array所表示的數組中,第一個索引值爲1,第二個索引值爲2,…
 netstat -tn | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}
 END{for (i in count) {print i,count[i]}}’

awk函數 自定義函數格式:

 function name ( parameter, parameter, ... ) {
 statements
 return expression
 }
 示例:
 cat fun.awk
 function max(x,y) {
 x>y?var=x:var=y
 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
 #!/bin/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

 

awk補充

awk [options] -f progfile [var=value] file ...
 awk [options] [var=value] 'program' file ...
 POSIX options:  GNU long options: (standard)
     -f progfile --file=progfile           從腳本文件中讀取awk命令
     -F fs       --field-separator=fs      指定分隔符,fs是一個字符串或正則表達式
     -v var=val  --assign=var=val          賦值一個自定義變量
 Short options:  GNU long options: (extensions)
     -b          --characters-as-bytes     將全部輸入數據視爲單字節字符(--posix覆蓋這個選項)
     -c          --traditional             在兼容模式下運行,awk=gawk
     -d[file]    --dump-variables[=file]   打印已排序的全局變量列表,沒有 file 打印幫助
     -e 'program-text'   --source='program-text'  使用 program-text 做爲AWK程序源代碼
     -g          --gen-pot                 掃描並解析AWK程序,生成一個GNU.pot
     可移植對象模板)格式的文件
     -n          --non-decimal-data        識別輸入數據中的八進制和十六進制值
     -r          --re-interval             在正則表達式匹配中啓用間隔表達式的使用 

 awk內置變量:
 $n            當前記錄的第n個字段,字段間由FS分隔
 $0            完整的輸入記錄
 ARGC          命令行參數的數目
 ARGIND        命令行中當前文件的位置(從0開始算)
 ARGV          包含命令行參數的數組
 CONVFMT       數字轉換格式(默認值爲%.6g)
 ENVIRON       環境變量關聯數組
 ERRNO         最後一個系統錯誤的描述
 FIELDWIDTHS   字段寬度列表(用空格鍵分隔)
 FILENAME      當前文件名
 FNR           各文件分別計數的行號
 FS            字段分隔符(默認是任何空格)
 IGNORECASE    若是爲真,則進行忽略大小寫的匹配
 NF            一條記錄的字段的數目
 NR            已經讀出的記錄數,就是行號,從1開始
 OFMT          數字的輸出格式(默認值是%.6g)
 OFS           輸出記錄分隔符(輸出換行符),輸出時用指定的符號代替換行符
 ORS           輸出記錄分隔符(默認值是一個換行符)
 RLENGTH       由match函數所匹配的字符串的長度
 RS            記錄分隔符(默認是一個換行符)
 RSTART        由match函數所匹配的字符串的第一個位置
 SUBSEP        數組下標分隔符(默認值是/034)

 = += -= *= /= %= ^= **=    賦值
 ?:                         C條件表達式
 ||                         邏輯或
 &&                         邏輯與
 ~ 和 !~                    匹配正則表達式和不匹配正則表達式
 < <= > >= != ==            關係運算符
 空格                        鏈接
 + -                        加,減
 * / %                      乘,除與求餘
 + - !                      一元加,減和邏輯非
 ^                          求冪
 ++ --                      增長或減小,做爲前綴或後綴
 $                          字段引用
 in                         數組成員

 條件語句
 if (expression) {
     statement;
     statement;
     ... ...
 }
 ​
 if (expression) {
     statement;
 } else {
     statement2;
 }
 ​
 if (expression) {
     statement1;
 } else if (expression1) {
 statement2;
 } else {
     statement3;
 }
 循環語句
 C語言:while、do/while、for、break、continue
 Examples:
 一.命令行方式調用awk
 awk [-F  field-separator]  'commands'  input-file(s)
 1 搜索/etc/passwd有root關鍵字的全部行
 awk -F: '/root/' /etc/passwd
 2 搜索/etc/passwd有root關鍵字的全部行,並顯示對應的shell
 awk -F: '/root/{print $7}' /etc/passwd
 3 打印/etc/passwd 中以:爲分隔符分割的每行第一項
 awk -F: '{ print $1 }' /etc/passwd
 4 使用","分割,-F至關於內置變量FS, 指定分隔符
 awk -F, '{print $1,$2}' filename
 awk 'BEGIN{FS=","} {print $1,$2}' filename
 5 使用多個分隔符:先使用空格分割,而後對分割結果再使用","分割
 awk -F '[ ,]' '{print $1,$2,$5}' filename
 6 統計 file 行數
 awk '{ sum += $1 }; END { print sum }' file
 7 統計用戶個數
 awk '{count++;print $0;} END{print "user count is ",count}' /etc/passwd  
 8 行匹配語句 awk '' 只能用單引號
 awk '{[pattern] action}' {filenames}
 9 每行輸出文本中的一、4項,按空格或TAB分割
 awk '{print $1,$4}' filename
 10 格式化每行輸出文本中的一、4項,按空格或TAB分割
 awk '{printf "%-8s %-10s\n",$1,$4}' filename   
 11 設置變量a=1,b=s,每行輸出文本中的1項、1項+a(數字求和,非數字直接是a)、1項添加後綴b,按空格或TAB分割
 awk -va=1 -vb=s '{print $1,$1+a,$1b}' filename 
 12 查看filename文件內第20到第30行的全部內容
 awk '{if(NR>=20 && NR<=30) print $0}' filename 
 13 統計當前目錄下文件總大小,以M爲單位輸出
 ll |awk 'BEGIN{size=0;} {size=size+$5;} END{print "[end]size is ",size/1024/1024,"M"}'  
 14 顯示/etc/passwd的帳戶,for循環遍歷數組
 awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
 15 按降序排序,篩選第二行小於70,統計總數(行數)
 sort -rnk2 1.txt|awk '$2<70'|wc-l
 二.shell腳本方式
 #!/bin/awk -f
 BEGIN{ 這裏面放的是執行前的語句 }
 {這裏面放的是處理每一行時要執行的語句}
 END {這裏面放的是處理完全部的行後要執行的語句 }
 三.將全部的awk命令插入一個單獨文件,而後調用
 awk -f awk-script-file input-file(s)

gsub函數的用法

 sub匹配第一次出現的符合模式的字符串,至關於 sed 's//'   
 gsub匹配全部的符合模式的字符串,至關於 sed 's//g'  
 例如:
 awk '{sub(/Mac/,"Macintosh");print}' urfile    用Macintosh替換Mac
 awk '{sub(/Mac/,"MacIntosh",$1); print}' file    第一個域內用Macintosh替換Mac
 把上面sub換成gsub就表示在知足條件得域裏面替換全部的字符。
 awk的sub函數用法:
 sub函數匹配指定域/記錄中最大、最靠左邊的子字符串的正則表達式,並用替換字符串替換這些字符串。
 若是沒有指定目標字符串就默認使用整個記錄。替換隻發生在第一次匹配的時候。格式以下:
 sub (regular expression, substitution string):
 sub (regular expression, substitution string, target string)
 實例:
 $ awk '{ sub(/test/, "mytest"); print }' testfile
 $ awk '{ sub(/test/, "mytest", $1); print }' testfile
 第一個例子在整個記錄中匹配,替換隻發生在第一次匹配發生的時候。
 第二個例子在整個記錄的第一個域中進行匹配,替換隻發生在第一次匹配發生的時候。
 如要在整個文件中進行匹配須要用到gsub
 gsub函數做用如sub,但它在整個文檔中進行匹配。格式以下:
gsub (regular expression, substitution string)
 gsub (regular expression, substitution string, target string)

 實例:
 $ awk '{ gsub(/test/, "mytest"); print }' testfile
 $ awk '{ gsub(/test/, "mytest", $1); print }' testfile
       第一個例子在整個文檔中匹配test,匹配的都被替換成mytest。
       第二個例子在整個文檔的第一個域中匹配,全部匹配的都被替換成mytest。
 另外, 只有當記錄中的域有改變的時候 ,指定0FS變量纔有用, 若是記錄中的域無變化, 指定OFS產生不了實際效果。

 awk -F'|' -v OFS='|' '{ gsub(/[0-9]/, "", $3); print $0; }' data.txt   
 將把第三個域中全部數字都去掉。
 
另外,對於數字的匹配,可使用十六進制。
​
 awk -F'|' -v OFS='|' '{ gsub(/[/x30-/x39]/, "", $3); print $0; }' data.txt 

基本正則表達式 BRE 元字符

 字符匹配:
 .            匹配任意單個字符
 []           匹配指定範圍內的任意單個字符,示例:[wang] [0-9] [a-z] [a-zA-Z]
 [^]          匹配指定範圍外的任意單個字符
 匹配次數:
 用在要指定次數的字符後面,用於指定前面的字符要出現的次數
 *         匹配前面的字符任意次,包括0次,貪婪模式:儘量長的匹配
  .*        任意長度的任意字符
  \?        匹配其前面的字符0或1次
  \+        匹配其前面的字符至少1次
  \{n\}     匹配前面的字符n次
  \{m,n\}   匹配前面的字符至少m次,至多n次
  \{,n\}    匹配前面的字符至多n次
 \{n,\}    匹配前面的字符至少n次
 匹配次數:
 用在要指定次數的字符後面,用於指定前面的字符要出現的次數
  *         匹配前面的字符任意次,包括0次,貪婪模式:儘量長的匹配
  .*        任意長度的任意字符
  \?        匹配其前面的字符0或1次
  \+        匹配其前面的字符至少1次
  \{n\}     匹配前面的字符n次
  \{m,n\}   匹配前面的字符至少m次,至多n次
  \{,n\}    匹配前面的字符至多n次
  \{n,\}    匹配前面的字符至少n次
 -  位置錨定:
 定位出現的位置
 ^               行首錨定,用於模式的最左側
 $               行尾錨定,用於模式的最右側
 ^PATTERN$       用於模式匹配整行
 ^$              空行
 ^[[:space:]]*$  空白行
 \< 或 \b        詞首錨定,用於單詞模式的左側
 \> 或 \b        詞尾錨定,用於單詞模式的右側
 \<PATTERN\>     匹配整個單詞
 \w              某個單詞
 分組:\(\) 
 將一個或多個字符捆綁在一塊兒,看成一個總體處理,如:\(root\)\+
 分組括號中的模式匹配到的內容,會被正則表達式引擎記錄於內部的變量中,
 這些變量的命名方式爲: \1, \2, \3, ...
 示例:
 \(string1\(string2\)\)
 \1 :string1\(string2\)  # 表示從左側起第一個左括號以及與之匹配右括號之間的模式所匹配到的字符。
 \2 :string2
 後向引用:引用前面的分組括號中的模式所匹配字符,而非模式自己
 ​
 或:\|
 示例:a\|b        a或b
      C\|cat      C或cat
      \(C\|c\)at  Cat或ca
 字符匹配:
 .   任意單個字符
 []  指定範圍的字符
 [^] 不在指定範圍的字符
 次數匹配:
 *     匹配前面字符任意次
 ?     0或1次
 +     1次或屢次
 {m}   匹配m次
 {m,n} 至少m,至多n次
 *     匹配前面字符任意次
 ?     0或1次
 +     1次或屢次
 {m}   匹配m次
 {m,n} 至少m,至多n次
 位置錨定:
 ^      行首
 $      行尾
 \<, \b 語首
 \>, \b 語尾
 \w     單詞
 分組:()
 ​
 後向引用:\1, \2, ...
 ​
 或:
 a|b      a或b
 C|cat    C或cat
 (C|c)at  Cat或cat
 特殊字符集
 字符集須要用 [ ] 來包含住,不然不會生效
 [:alnum:]    字母和數字
 [:alpha:]    表明任何英文大小寫字符,亦即 A-Z, a-z
 [:lower:]    小寫字母 
 [:upper:]    大寫字母
 [:blank:]    空白字符(空格和製表符)
 [:space:]    水平和垂直的空白字符(比[:blank:]包含的範圍廣)
 [:cntrl:]    不可打印的控制字符(退格、刪除、警鈴...)
 [:digit:]    十進制數字 
 [:xdigit:]   十六進制數字
 [:graph:]    可打印的非空白字符
 [:print:]    可打印字符
 [:punct:]    標點符號
 *                 匹配任意零個或多個字符
 ?                 匹配任意一個字符
 [0-9]             匹配任意數字
 [a-z]             匹配任意小寫字母
 [A-Z]             匹配任意大寫字母
 []                匹配中括號裏任意一個字符,- 指定範圍
 [^] ; [!]         匹配中括號裏任意字符之外的字符,取反
 大括號擴展
 &>>file    把 標準輸出 和 標準錯誤 都追加劇定向到file

練習題:

一、文件ip_list.txt以下格式,請提取」.magedu.com」前面的主機名部分並寫入到回到該文件中 1 blog.magedu.com 2 www.magedu.com 999 study.magedu.com

 [root.CentOS 7] ~ awk -F. '{print $1}' ip-list.txt >> ip-list.txt

二、統計/etc/fstab文件中每一個文件系統類型出現的次數

 [root.CentOS 7] ➤ awk '/^[^#].*$/{print $3}' /etc/fstab |sort|uniq -c

三、統計/etc/fstab文件中每一個單詞出現的次數

 [root.CentOS 7] ➤ awk 'gsub(/[^[:alpha:]]/,"\n",$0)' /etc/fstab | sort|uniq -c

四、提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的全部數字

 [root.CentOS 7] ➤ echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw" | awk 'gsub(/[^[:digit:]]/,"",$0)'

五、有一文件記錄了1-100000之間隨機的整數共5000個,存儲的格式100,50,35,89…請取出其中最大和最小的整數

 awk -F, '{if($1>$2){big=$1;small=$2}\
 else{big=$2;small=$1}\
 for(i=3;i<=NF;i++){\
 if(big<$i){big=$i}\
 if(small>$i){small=$i}\
 }}\
 END{print "big:"big"\nsmall:"small}' RANDOM.txt

六、解決DOS攻擊生產案例:根據web日誌或者或者網絡鏈接數,監控當某個IP併發鏈接數或者短時內PV達到100,即調用防火牆命令封掉對應的IP,監控頻率每隔5分鐘。防火牆命令爲:iptables -A INPUT -s IP -j REJECT

 >crontab -e
 */5 * * * * bash dos.sh
 >cat dos.sh
 #!/bin/bash
 ss -t | awk -F "[[:space:]]+|:" '{count[$6]++;}END{for(i in count){if(count[i]>1){system("iptables  -A INPUT -s " i " -j REJECT")}}}'

七、將如下文件內容中FQDN取出並根據其進行計數從高到低排序

http://mail.magedu.com/index.html
http://www.magedu.com/test.html
http://study.magedu.com/index.html
http://blog.magedu.com/index.html
http://www.magedu.com/images/logo.jpg
http://blog.magedu.com/20080102.html
[root.CentOS 7] ➤ awk -F "[/|.]" '{count[$3]++}END{for(i in count){print i,count[i]}}' url.txt

八、將如下文本以inode爲標記,對inode相同的counts進行累加,而且統計出同一inode中,beginnumber的最小值和endnumber的最大值

 inode|beginnumber|endnumber|counts| 106|3363120000|3363129999|10000| 106|3368560000|3368579999|20000| 310|3337000000|3337000100|101| 310|3342950000|3342959999|10000| 310|3362120960|3362120961|2| 311|3313460102|3313469999|9898| 311|3313470000|3313499999|30000| 311|3362120962|3362120963|2| 輸出的結果格式爲: 310|3337000000|3362120961|10103| 311|3313460102|3362120963|39900| 106|3363120000|3368579999|30000|
 awk -F "|" -v OFS="|" 'NR==1{print $0}\
 NR>1{count[$1]+=$4;if(max[$1]<$3){max[$1]=$3}\
 if(!min[$1]){min[$1]=$2}if(min[$i]>$2){min[$1]=$2}}\
 END{for(i in count){print i,min[i],max[i],count[i]"|"}}' inode.txt
相關文章
相關標籤/搜索