Shell腳本之awk詳解正則表達式
一.基本介紹數組
1.awk:bash
awk是一個強大的文本分析工具,在對文本文件的處理以及生成報表,awk是無可替代的。awk認爲文本文件都是結構化的,它將每個輸入行定義爲一個記錄,行中的每一個字符串定義爲一個域(段),域和域之間使用分割符分割。ide
2.功能:流控制、數學運算、進程控制、內置的變量和函數、循環和判斷函數
3.工做原理:工具
awk 會把每行進行一個拆分,用相應的命令對拆分出來的「段」進行處理。測試
(1)行工做模式,讀入文件的每一行,會把一行的內容,存到$0裏this
(2)使用內置的變量FS(段的分隔符,默認用的是空白字符),分割這一行,把分割出來的每一個段存到相應的變量$(1-100)spa
(3)輸出的時候按照內置變量OFS(out FS),輸出命令行
(4)讀入下一行繼續操做
簡單實例
[root@tx3 ~]# echo "this is a book" > awk.txt
[root@tx3 ~]# awk '{print $2,$1,$3,$4}' awk.txt
is this a book
4. Awk經常使用內置變量表:
1 $0 當前記錄(做爲單個變量)
2 $1~$n 當前記錄的第n個字段,字段間由FS分隔
3 FS 輸入字段分隔符 默認是空格
4 NF 當前記錄中的字段個數,就是有多少列
5 NR 已經讀出的記錄數,就是行號,從1開始
6 RS 輸入的記錄他隔符默 認爲換行符
7 OFS 輸出字段分隔符 默認也是空格
8 ORS 輸出的記錄分隔符,默認爲換行符
9 ARGC 命令行參數個數
10 ARGV 命令行參數數組
11 FILENAME 當前輸入文件的名字
12 IGNORECASE 若是爲真,則進行忽略大小寫的匹配
13 ARGIND 當前被處理文件的ARGV標誌符
14 CONVFMT 數字轉換格式 %.6g
15 ENVIRON UNIX環境變量
16 ERRNO UNIX系統錯誤消息
17 FIELDWIDTHS 輸入字段寬度的空白分隔字符串
18 FNR 當前記錄數
19 OFMT 數字的輸出格式 %.6g
20 RSTART 被匹配函數匹配的字符串首
21 RLENGTH 被匹配函數匹配的字符串長度
二.print的簡單使用
例:打印整行: $0
[root@tx3 ~]# cp /etc/passwd p1
[root@tx3 ~]# awk '{print $0}' p1
例:打印每行的最後一個字段: $NF
[root@tx3 ~]# awk -F : '{print $NF}' p1
例:打印第三個字段: $3
[root@tx3 ~]# awk -F : '{print $3}' p1
例:打印第一行NR==1
[root@tx3 ~]# awk 'NR==1{print $0}' p1
root:x:0:0:root:/root:/bin/bash
例:打印最後一行
[root@tx3 ~]# awk 'END{print $0}' p1
tx:x:500:500:tx:/home/tx:/bin/bash
例:打印第一行最後一個字段
[root@tx3 ~]# awk -F: 'NR==1{print $NF}' p1
/bin/bash
例:打印最後一行最後一個字段
[root@tx3 ~]#awk -F: 'END{print $NF}' p1
例:打印每行的倒數第二個字段,並在其後打印你好
[root@tx3 ~]# awk -F: '{print $(NF-1),"nihao"}' p1
/root nihao
/bin nihao
/sbin nihao
例:打印行號
[root@tx3 ~]# awk '{print NR,$0}' p1
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
例:打印當前系統環境變量的某個特定值
[root@tx3 ~]# awk 'BEGIN{print ENVIRON["PATH"];}'
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
例: 用:分割,刪除第2個字段
[root@tx3 ~]# awk 'BEGIN{FS=":";OFS=":"}{print $1,$3,$4,$5,$6,$7}' p1
root:0:0:root:/root:/bin/bash
bin:1:1:bin:/bin:/sbin/nologin
daemon:2:2:daemon:/sbin:/sbin/nologin
三.printf的使用
print format 生成報表
%d 十進制有符號整數
%u 十進制無符號整數
%f 浮點數
%s 字符串
%c 顯示字符的ASCII碼
%p 指針的值
%e 科學技術法顯示數值
%x %X 無符號以十六進制表示的整數
%o 無符號以八進制表示的整數
%g %G 以科學計數法或浮點數的格式顯示數值
%% 顯示其自身
修飾符:
-: 左對齊
+: 顯示數值符號
N: 顯示
-F 指定段的分隔符
例:(1)生成報表
例:(2)小數問題
對小數取保留位的時候,四捨五入
對小數取整,不進行四捨五入
[root@tx3 ~]# cat awk.1
23.3456 11.234 45.67
[root@tx3 ~]# awk '{printf "%.2f\t%.2f\t%.2f\n",$1,$2,$3}' awk.1
23.3511.2345.67
四.awk的使用
(1)正則表達式
\(\) \{\} 不支持
. * ^ $ ? + [] | \< \> () 能夠直接使用
例[root@tx3 ~]# awk '/^$/{print "this is an empty line"}' /etc/inittab
this is an empty line
this is an empty line
this is an empty line
this is an empty line
this is an empty line
this is an empty line
this is an empty line
this is an empty line
this is an empty line
例[root@tx3 ~]# awk -F: '/^root/{print $1,$NF}' /etc/passwd
root /bin/bash
例[root@tx3 ~]# awk -F: '!/^root/{print $1,$NF}' /etc/passwd|head -3
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
(2)關係運算符
> < == != >= <=
~(匹配) !~(不匹配)
例[root@tx3 ~]# cp /etc/passwd p1
[root@tx3 ~]# awk -F: '$3 == 0 {print $1}' p1
Root
例[root@tx3 ~]# awk -F: '$3 != 0{ print $1}' p1 | head -2
bin
Daemon
例[root@tx3 ~]# awk -F: '$3 < 2 {print $1}' p1
root
bin
(3)邏輯運算符
&& || !
與 或 非
例[root@tx3 ~]# awk -F: '$3 > 0 && $3 < 10 {print $1, $3}' p1 |head -2
bin 1
daemon 2
例[root@tx3 ~]# awk -F: '$3 > 10 || $3 < 5 {print $1,$3}' p1 |head -6
root 0
bin 1
daemon 2
adm 3
lp 4
operator 11
(4)算數運算符
+ - * / %(取模(餘數)) ^(冪運算)
例:輸出名字,總成績,平均成績
[root@tx3 ~]# cat cj
tx 90 86 86
tx1 89 78 85
tx2 79 80 85
[root@tx3 ~]# awk '{print $1,$2+$3+$4,($2+$3+$4)/3}' cj
tx 262 87.3333
tx1 252 84
tx2 244 81.3333
[root@tx3 ~]# awk '{printf"%-5s %3d %.2f\n",$1,$2+$3+$4,($2+$3+$4)/3}' cj
tx 262 87.33
tx1 252 84.00
tx2 244 81.33
(5)BEGIN END
BEGIN{ 動做;動做;... } 在處理文件以前,要執行的動做;只執行一次
END{ 動做;動做;... } 在處理完文件以後,要執行的動做;只執行一次
BEGIN :能夠給文件添加標題、定義變量、定義文件的分隔符
END:彙總的操做
getline能夠從管道和標準輸入讀取輸入,而後傳遞給變量。
例:
[root@tx3 ~]# awk 'BEGIN{"date"| getline a}{print}END{print a}' cj
tx 90 86 86
tx1 89 78 85
tx2 79 80 85
Thu Feb 7 12:39:25 CST 2013
五.awk裏的流控制和循環
(1)簡單的條件判斷
語法:(表達式 ? 值1 : 值2) 若是表達式成立,輸出值1;不然輸出值2
[root@tx3 ~]# cat num
2 8 9
8 4 6
3 5 7
[root@tx3 ~]# awk '{print ( $1 > $2 ? $1 : $2)}' num
8
8
5
(2)if判斷
語法:
{ if (表達式
{
動做1;動做2;...
}
}
若是表達式成立,那麼執行動做。
[root@tx3 ~]# awk '{if ($2>=80 && $2 <=100) {print $1,"great"} else {print $1, "good"}}' cj
tx great
tx1 great
tx2 good
(2)多支判斷
{
if (表達式)
{ 動做1;動做2;...}
else if (表達式)
{ 動做1;動做2;...}
else if (表達式)
{ 動做1;動做2;...}
......
else
{ 動做1;動做2;...}
}
[root@tx3 ~]# cat cj
tx 90 86 86
tx1 89 78 85
tx2 79 80 85
tx3 80 70 60
tx4 75 85 65
tx5 78 62 80
判斷的標準:
90-100 A
80-89 B
70-79 C
60-69 D
0-59 E
[root@tx3 ~]# awk '{ if ($2 >= 90 && $2 <= 100) {print $1,"A"} else if ($2 >= 80 && $2 < 90) {print $1,"B"} else if ($2 >= 70 && $2 < 80) {print $1,"C"} else if ($2 >= 60 && $2 < 70) {print $1,"D"} else {print $1,"E"} }' cj
tx A
tx1 B
tx2 C
tx3 B
tx4 C
tx5 C
(3)循環while
語法:'var=初值;while (表達式){動做1;...更新變量的動做;}'
例:
[root@tx3 ~]# awk -F: '{i=1; while (i<=NF) {print $i;i++}}' p1 | head -7
root
x
0
0
root
/root
/bin/bash
例. 方法一
[root@tx3 ~]# awk -F: '{i=NF; while (i>=2) {printf $i ":";i--};print $1}' p1
/bin/bash:/root:root:0:0:x:root
/sbin/nologin:/bin:bin:1:1:x:bin
/sbin/nologin:/sbin:daemon:2:2:x:daemon
/sbin/nologin:/var/adm:adm:4:3:x:adm
例. 方法二
[root@tx3 ~]# awk 'BEGIN { FS=":" } { i=NF; while (i>=2) {printf $i ":";i--} print $1}' p1
/bin/bash:/root:root:0:0:x:root
/sbin/nologin:/bin:bin:1:1:x:bin
/sbin/nologin:/sbin:daemon:2:2:x:daemon
(4)for循環
語法:
{
for(表達式)
{動做1;...}
}
表達式:分爲3部分:
(1)初始化表達式 i=1
(2)測試表達式 i<10
(3)更新測試表達式 i++
語句:
next 處理輸入行的下一個輸入行
exit 退出
continue 結束本次循環
break 跳出循環
例
[root@tx3 ~]# awk 'BEGIN {FS=":"} {for(i=NF;i>=2;i--) {printf $i ";"};print $1}' p1
/bin/bash;/root;root;0;0;x;root
/sbin/nologin;/bin;bin;1;1;x;bin
/sbin/nologin;/sbin;daemon;2;2;x;daemon
/sbin/nologin;/var/adm;adm;4;3;x;adm
例
[root@tx3 ~]# cat num
2 8 9
8 4 6
3 5 7
[root@tx3 ~]# awk '{ max=0; i=1; while (i<=NF) { if (max<$i) {max=$i} i++} print max}' num
9
8
7
(5)awk數組
例
例 使用變量做爲數組下標
另一種讀取方式(這種是無序的,j是變量,a是數組)
數組有序
(6)函數
@1split 切割字符串
split("等待被切割的字符串",數組名,"切割用的分隔符")
[root@tx3 ~]# awk 'BEGIN{split("2012/08/23",da,"/");print da[2],da[3],da[1]}'
08 23 2012
@2toupper() 小寫轉大寫
tolower() 大寫轉小寫
[root@tx3 ~]# awk '{print toupper($0)}' p1 |head -3
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN
DAEMON:X:2:2:DAEMON:/SBIN:/SBIN/NOLOGIN
@3sub() 局部替換
gsub() 全局替換
sub(/要替換的內容/,"替換成什麼內容")
gsub(/要替換的內容/,"替換成什麼內容")
gsub(/要替換的內容/,"替換成什麼內容",指定字段如$7)
例:
[root@tx3 ~]# awk -F: '{sub(/root/,"r00t");print}' p1
r00t:x:0:0:root:/root:/bin/bash
例:
[root@tx3 ~]# awk -F: '{gsub(/root/,"r00t");print}' p1
r00t:x:0:0:r00t:/r00t:/bin/bash
operator:x:11:0:operator:/r00t:/sbin/nologin
例:
[root@tx3 ~]# awk -F[:/] '{gsub(/root/,"r00t",$7);print}' p1
root x 0 0 root r00t bin bash
operator x 11 0 operator r00t sbin nologin
@4.length() 計算字符串的長度
[root@tx3 ~]# awk -F: '{print length($1),$1}' p1
4 root
3 bin
6 daemon
3 adm
@5. 數學計算
[root@tx3 ~]# awk 'BEGIN{print sin(30)}'
-0.988032
[root@tx3 ~]# awk 'BEGIN{print cos(60)}'
-0.952413
[root@tx3 ~]# awk 'BEGIN{print int(22/6)}'
3
[root@tx3 ~]# awk 'BEGIN{print sqrt(3)}'
1.73205