awk 内嵌正则 提取字符串_干货-Shell编程文本处理三剑客之-awk
awk
在 Linux/UNIX 系統(tǒng)中,awk 是一個(gè)功能強(qiáng)大的編輯工具,逐行讀取輸入文本,并根據(jù)指定的匹配模式進(jìn)行查找,對(duì)符合條件的內(nèi)容進(jìn)行格式化輸出或者過(guò)濾處理,可以在無(wú)交互的情況下實(shí)現(xiàn)相當(dāng)復(fù)雜的文本操作,被廣泛應(yīng)用于 Shell 腳本,完成各種自動(dòng)化配置任務(wù)。
AWK是一種處理文本文件的語(yǔ)言,是一個(gè)強(qiáng)大的文本分析工具。之所以叫 AWK 是因?yàn)槠淙×巳粍?chuàng)始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
語(yǔ)法格式:
語(yǔ)法格式解釋:
| BEGIN{} | 正式處理數(shù)據(jù)之前執(zhí)行 |
| pattern | 匹配模式 |
| {commands} | 處理命令,可能多行 |
| END{} | 處理完所有匹配數(shù)據(jù)后執(zhí)行 |
awk內(nèi)置變量
| $0 | 整行內(nèi)容 |
| $1~$n | 當(dāng)前行的第1-n個(gè)字段 |
| NF | 當(dāng)前行的字段個(gè)數(shù),也就是有多少列 |
| NR | 當(dāng)前行的行號(hào),從1開始計(jì)數(shù) |
| FNR | 多文件處理時(shí),每個(gè)文件行號(hào)單獨(dú)計(jì)數(shù)都是從0開始 |
| FS | 輸入字段分隔符,不指定則默認(rèn)以空格或tab鍵分隔 |
| RS | 輸入行分隔符,默認(rèn)回車換行 |
| OFS | 輸出字段分隔符,默認(rèn)為空格 |
| ORS | 輸出行分隔符,默認(rèn)回車換行 |
| FILENAME | 當(dāng)前輸入的文件名字 |
| ARGC | 命令行參數(shù)個(gè)數(shù) |
| ARGV | 命令行參數(shù)數(shù)組 |
示例
以下所有示例文件為/etc/passwd,請(qǐng)將其拷貝一份使用
# 打印整行內(nèi)容 awk '{print $0}' passwd# 使用":"號(hào)作為分隔符,輸出第一個(gè)字段 awk 'BEGIN{FS=":"}{print $1}' passwd ->root ->bin ->daemon ->adm ->lp ->sync ->shutdown ->...# 輸出行號(hào) awk '{print NR}' passwd# 多個(gè)文件行號(hào)單獨(dú)計(jì)數(shù) awk '{print FNR}' passwd file2# 指定行分隔符 echo "hello-world-hello-linux-hello-java" | awk 'BEGIN{RS="-"}{print $0}' ->hello ->world ->hello ->linux ->hello ->java -># 指定輸出字段分隔符 awk 'BEGIN{FS=":";OFS=":"}{print NR,$1}' passwd ->1:root ->2:bin ->3:daemon ->4:adm ->5:lp ->...printf格式化輸出
| %s | 打印字符串 |
| %d | 打印十進(jìn)制數(shù) |
| %f | 打印一個(gè)浮點(diǎn)數(shù) |
| %x | 打印十六進(jìn)制數(shù) |
| %o | 打印八進(jìn)制數(shù) |
| %e | 打印數(shù)字的科學(xué)計(jì)數(shù)法形式 |
| %c | 打印單個(gè)字符的ASCII碼 |
| - | 左對(duì)齊 |
| + | 右對(duì)齊 |
| # | 顯示8進(jìn)制在前面加0,顯示16進(jìn)制在前面加0x |
示例
# 以字符串格式打印第1個(gè)字段,以":"作為分隔符 awk 'BEGIN{FS=":"}{printf "%st",$1}' passwd ->root bin daemon adm lp ...# 以字符串格式打印第1個(gè)字段和對(duì)應(yīng)行號(hào),輸出格式為"行號(hào):字段內(nèi)容" awk 'BEGIN{FS=":"}{printf "%d:%sn",NR,$1}' passwd ->1:root ->2:bin ->3:daemon ->4:adm ->5:lp ->...# 左對(duì)齊 # 在不指定位數(shù)的情況下默認(rèn)左對(duì)齊,指定位數(shù)后為右對(duì)齊(必須指定位數(shù)) awk 'BEGIN{FS=":"}{printf "%10d:%sn",NR,$1}' passwd -> 1:root -> 2:bin -> 3:daemon -> 4:adm -> 5:lp ->...awk 'BEGIN{FS=":"}{printf "%-10d:%sn",NR,$1}' passwd ->1 :root ->2 :bin ->3 :daemon ->4 :adm ->5 :lp ->...兩種匹配模式
| 正則 | 按正則表達(dá)式匹配 |
| 關(guān)系運(yùn)算 | 按關(guān)系運(yùn)算匹配 |
關(guān)系運(yùn)算符:
- < : 小于
- > : 大于
- <= : 小于等于
- >= : 大于等于
- == : 等于
- != : 不等于
- ~ : 匹配正則表達(dá)式
- !~ : 不匹配正則表達(dá)式
布爾運(yùn)算符:
- || : 或
- && : 與
- ! : 非
awk表達(dá)式
# 統(tǒng)計(jì)空白行數(shù)目 awk '/^$/{sum++}END{print sum}' /etc/services ->17# 統(tǒng)計(jì)一下學(xué)生成績(jī)總分和平均分,報(bào)表形式展示 姓名 語(yǔ)文 數(shù)學(xué) 英語(yǔ) 物理 張三 80 60 85 90 李四 85 65 80 75 王五 70 60 85 90 李華 65 80 84 91 王八 90 90 95 90awk 'BEGIN{printf "%-8s%-5s%-5s%-5s%-5s%-5s%-8sn","姓名","語(yǔ)文","數(shù)學(xué)","英語(yǔ)","物理","總分","平均分"}{total=$2+$3+$4+$5;avg=total/4;printf "%-8s%-8d%-6d%-8d%-7d%-5d%0.2fn",$1,$2,$3,$4,$5,total,avg}' stu.txt姓名 語(yǔ)文 數(shù)學(xué) 英語(yǔ) 物理 總分 平均分 張三 80 60 85 90 315 78.75 李四 85 65 80 75 305 76.25 王五 70 60 85 90 305 76.25 李華 65 80 84 91 320 80.00 王八 90 90 95 90 365 91.25條件語(yǔ)句和循環(huán)語(yǔ)句
# 條件語(yǔ)句 if (條件表達(dá)式1){action1 }else if (條件表達(dá)式2){action2 }else{action3 }# 以":"為分隔符,如果第3個(gè)字段小于50,打印小于50,如果等于50則打印等于50,否則打印大于50 awk 'BEGIN{FS=":"}{if($3<50){print "小于50" }else if($3==50){ print "等于50"}else{print "大于50"}}' passwd# 我們可以將命令保存在一個(gè)文件(eg:oper.awk,后綴不硬性要求哦!)中使用-f選項(xiàng)引入 awk -f oper.awk passwd# 循環(huán)語(yǔ)句 while while(條件表達(dá)式){action }# 循環(huán)語(yǔ)句 do while do{action }while(條件表達(dá)式)# 循環(huán)語(yǔ)句 for for(初始化計(jì)數(shù)器;測(cè)試計(jì)數(shù)器;變更計(jì)數(shù)器){action }# 計(jì)算1+2+3+...+100的和。 awk 'BEGIN{do{i++;sum+=i;}while(i<100)print sum}' awk 'BEGIN{while(i<100){i++;sum+=i;}print sum}' awk 'BEGIN{for(i=0;i<=100;i++){sum+=i;}print sum}'字符串函數(shù)
| length(str) | 計(jì)算字符串長(zhǎng)度 | 整數(shù)長(zhǎng)度值 |
| index(str1,str2) | 在str1中查找str2的位置 | 位置索引,從1計(jì)數(shù) |
| tolower(str) | 轉(zhuǎn)換為小寫 | 轉(zhuǎn)換后的小寫字符串 |
| toupper(str) | 轉(zhuǎn)換為大寫 | 轉(zhuǎn)換后的大寫字符串 |
| substr(str,m,n) | 從str的m個(gè)字符開始,截取n位 | 截取后的子串 |
| split(str,arr,fs) | 按fs切割字符串,結(jié)果保存在arr中 | 切割后的子串個(gè)數(shù) |
| match(str,RE) | 在str中按照RE查找,返回位置 | 返回索引位置 |
| sub(RE,RepStr,str) | 在str中搜索符合RE的子串,將其替換為RepStr,只替換第一個(gè) | 替換的個(gè)數(shù) |
| gsub(RE,RepStr,str) | 在str中搜索符合RE的子串,將其替換為RepStr,替換所有 | 替換的個(gè)數(shù) |
示例
# 以:為分隔符,返回文件每行中每個(gè)字段的長(zhǎng)度 awk 'BEGIN{FS=":"}{for(i=1;i<=NF;i++){if(i==NF){printf "%d",length($i)}else{printf "%d:",length($i)}}print ""}' passwd# 搜索字符串"I am a student"中student子串的位置 echo "I am a student" | awk '{print index($0,"student")}' ->8awk常用選項(xiàng)
| -v | 參數(shù)傳遞 |
| -f | 指定腳本文件 |
| -F | 指定分隔符 |
| -V | 查看awk版本號(hào) |
數(shù)組
awk中數(shù)組使用小括號(hào)包圍起來(lái),每一項(xiàng)之間使用空格分隔,如:arr=("one" "two" "three" "four" "five").在awk中數(shù)組下標(biāo)從1開始,需要注意哦~。 awk可以使用關(guān)聯(lián)數(shù)組這種數(shù)據(jù)結(jié)構(gòu),索引可以是數(shù)字或字符串。awk關(guān)聯(lián)數(shù) 組也不需要提前聲明其大小,因?yàn)樗谶\(yùn)行時(shí)可以自動(dòng)的增大或減小。
# 統(tǒng)計(jì)主機(jī)上所有的TCP,按照TCP狀態(tài)進(jìn)行分類 netstat -an | grep tcp | awk '{array[$6]++}END{for(item in array){print item,array[item]}}' ->LISTEN 8 ->ESTABLISHED 26awk文件處理
awk 可以直接處理目標(biāo)文件,也可以通過(guò)“-f”讀取腳本對(duì)目標(biāo)文件進(jìn)行處理。
(1) awk 比較傾向于將一行分成多個(gè)“字段”然后再進(jìn)行處理,且默認(rèn)情況下字段的分隔符為空格或者 tab 鍵。awk 執(zhí)行結(jié)果可以通過(guò) print 的功能將字段數(shù)據(jù)打印顯示。在使用 awk 命令的過(guò)程中,可以使用
邏輯操作符如下所示:
*“&&”,表示“與”* *“||”,表示“或”* *“!”,表示“非”*簡(jiǎn)單的數(shù)學(xué)運(yùn)算如下:
+、-、*、/、%、^分別 表示加、減、乘、除、取余和乘方(2)在 Linux 系統(tǒng)中/etc/passwd 是一個(gè)非常典型的格式化文件,各字段間使用“:”作為分隔符隔開,Linux 系統(tǒng)中的大部分日志文件也是格式化文件,從這些文件中提取相關(guān)信息是運(yùn)維的日常工作內(nèi)容之一。
例如:需要查找出/etc/passwd 的用戶名、用戶 ID、組 ID 等列, 執(zhí)行以下 awk 命令即可。
[root@localhost ~]# awk -F ':' '{print $1,$3,$4}' /etc/passwd root 0 0 bin 1 1 daemon 2 2 adm 3 4 lp 4 7 sync 5 0 shutdown 6 0 halt 7 0 mail 8 12 operator 11 0 games 12 100 ftp 14 50 //省略部分內(nèi)容awk 從輸入文件或者標(biāo)準(zhǔn)輸入中讀入信息,與 sed 一樣,信息的讀入也是逐行讀取的。不同的是 awk 將文本文件中的一行視為一個(gè)記錄,而將一行中的某一部分(列)作為記錄中的一個(gè)字段(域)。為了操作這些不同的字段,awk 借用 shell 中類似于位置變量的方法, 用$1、$2、$3?順序地表示行(記錄)中的不同字段。另外 awk 用$0 表示整個(gè)行(記錄)。不同的字段之間是通過(guò)指定的字符分隔。awk 默認(rèn)的分隔符是空格。awk 允許在命令行中用“-F 分隔符”的形式來(lái)指定分隔符。因此,上述示例中,awk 命令對(duì)/etc/passwd 文件的處理過(guò)程如圖 所示:
awk工作原理圖(3)awk 包含幾個(gè)特殊的內(nèi)建變量(可直接用):
- FS:指定每行文本的字段分隔符,默認(rèn)為空格或制表位。
- NF:當(dāng)前處理的行的字段個(gè)數(shù)。
- NR:當(dāng)前處理的行的行號(hào)(序數(shù))。
- $0:當(dāng)前處理的行的整行內(nèi)容。
- $n:當(dāng)前處理行的第 n 個(gè)字段(第 n 列)。
- FILENAME:被處理的文件名。
- RS:數(shù)據(jù)記錄分隔,默認(rèn)為n,即每行為一條記錄。
用法示例
(1)按行輸出文本
輸出所有內(nèi)容
[root@localhost opt]# awk '{print}' test.txt //輸出所有內(nèi)容,等同于 cat test.txt或者
[root@localhost opt]# awk '{print $0}' test.txt //輸出所有內(nèi)容,等同于 cat test.txt輸出1-3行內(nèi)容
[root@localhost opt]# awk 'NR==1,NR==3{print}' test.txt //輸出第 1~3 行內(nèi)容 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin或者
[root@localhost opt]# awk '(NR>=1)&&(NR<=3){print}' test.txt //輸出第 1~3 行內(nèi)容 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin輸出以root 開頭的行
[root@localhost opt]# awk '/^root/{print}' /etc/passwd root:x:0:0:root:/root:/bin/bash輸出以 nologin 結(jié)尾的行
[root@localhost opt]# awk '/nologin$/{print}' /etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin polkitd:x:999:998:User for polkitd:/:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin libstoragemgmt:x:998:996:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin chrony:x:995:991::/var/lib/chrony:/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 ntp:x:38:38::/etc/ntp:/sbin/nologin tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin geoclue:x:994:989:User for geoclue:/var/lib/geoclue:/sbin/nologin qemu:x:107:107:qemu user:/:/sbin/nologin radvd:x:75:75:radvd user:/:/sbin/nologin setroubleshoot:x:993:988::/var/lib/setroubleshoot:/sbin/nologin sssd:x:992:987:User for sssd:/:/sbin/nologin gdm:x:42:42::/var/lib/gdm:/sbin/nologin gnome-initial-setup:x:991:986::/run/gnome-initial-setup/:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin dhcpd:x:177:177:DHCP server:/:/sbin/nologin統(tǒng)計(jì)以/bin/bash 結(jié)尾的行數(shù),等同于 grep -c "/bin/bash$" /etc/passwd
[root@localhost opt]# awk 'BEGIN{X=0};//bin/bash$/{x++};END{print x}' /etc/passwd 11統(tǒng)計(jì)以空行分隔的文本段落數(shù)
[root@localhost ~]# awk 'NEGIN{RS=""};END{print NR}' /etc/passwd 52(2)按字段輸出文本
輸出每行中(以空格或制表位分隔)的第 3 個(gè)字段
[root@localhost ~]# awk '{print $3}' /etc/passwdManagement:/:/sbin/nologinbus:/:/sbin/nologinpolkitd:/:/sbin/nologinforcolord:/var/lib/colord:/sbin/nologinDaemon:/var/run/pulse:/sbin/nologinUser:/var/lib/nfs:/sbin/nologin User:/var/lib/nfs:/sbin/nologinbygeoclue:/var/lib/geoclue:/sbin/nologinsssd:/:/sbin/nologinStack:/var/run/avahi-daemon:/sbin/nologin[root@localhost ~]#輸出每行中的第 1、3 個(gè)字段
[root@localhost ~]# awk '{print $1,$3}' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync輸出密碼為空的用戶的shadow 記錄
[root@localhost ~]# awk -F ":" '$2==""{print}' /etc/shadow或者
[root@localhost ~]# awk 'BEGIN{FS=":"};$2==""{print}' /etc/shadow輸出以冒號(hào)分隔且第 7 個(gè)字段中包含/bash 的行的第 1 個(gè)字段
[root@localhost ~]# awk -F ":" '$7~"/bash"{print $1}' /etc/passwd root shan lisi wangwu zhangsan liuliu c xiao jing tol jiji sfya輸出包含 8 個(gè)字段且第 1 個(gè)字段中包含 nfs 的行的第 1、2 個(gè)字段
[root@localhost ~]# awk '($1~"nfs")&&(NF==8){print $1,$2}' /etc/services nfs 2049/tcp nfs 2049/udp nfs 2049/sctp netconfsoaphttp 832/tcp netconfsoaphttp 832/udp netconfsoapbeep 833/tcp netconfsoapbeep 833/udp輸出第 7 個(gè)字段既不為/bin/bash 也不為/sbin/nologin 的所有行
[root@localhost ~]# awk -F ":" '($7!="/bin/bash")&&($7!="/sbin/nologin"){print}' /etc/passwd sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt*(3)通過(guò)管道、雙引號(hào)調(diào)用 Shell 命令*
調(diào)用wc -l 命令統(tǒng)計(jì)使用bash 的用戶個(gè)數(shù),等同于 grep -c "bash$" /etc/passwd
[root@localhost ~]# awk -F : '/bash$/{print | "wc -l"}' /etc/passwd 12調(diào)用w 命令,并用來(lái)統(tǒng)計(jì)在線用戶數(shù)
[root@localhost ~]# awk 'BEGIN{while("w" | getline)n++;{print n-2}}' 4調(diào)用hostname,并輸出當(dāng)前的主機(jī)名
[root@localhost ~]# awk 'BEGIN{"hostname" | getline;print $0}' localhost.localdomain總結(jié)
以上是生活随笔為你收集整理的awk 内嵌正则 提取字符串_干货-Shell编程文本处理三剑客之-awk的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python如何让用户输入文件名并打开文
- 下一篇: 事务对性能影响_开启英特尔事务扩展技术(