正則就是用一些具備特殊含義的符號組合到一塊兒(稱爲正則表達式)來描述字符或者字符串的方法。或者說:正則就是用來描述一類事物的規則。linux
生活中到處都是正則:git
好比咱們描述:4條腿正則表達式
你可能會想到的是四條腿的動物或者桌子,椅子等shell
繼續描述:4條腿,活的express
就只剩下四條腿的動物這一類了數組
在linux中,通配符是由shell解釋的,而正則表達式則是由命令解釋的,下面咱們就爲你們介紹三種文本處理工具/命令:grep、sed、awk,它們三者都可以解釋正則。bash
參數ssh
-n :顯示行號
-o :只顯示匹配的內容
-q :靜默模式,沒有任何輸出,得用$?來判斷執行成功沒有,即有沒有過濾到想要的內容編輯器
-l :若是匹配成功,則只將文件名打印出來,失敗則不打印,一般-rl一塊兒用,grep -rl 'root' /etc
-A :若是匹配成功,則將匹配行及其後n行一塊兒打印出來
-B :若是匹配成功,則將匹配行及其前n行一塊兒打印出來
-C :若是匹配成功,則將匹配行及其先後n行一塊兒打印出來
--color
-c :若是匹配成功,則將匹配到的行數打印出來
-E :等於egrep,擴展
-i :忽略大小寫ide
-v :取反,不匹配
-w:匹配單詞
[root@MiWiFi-R3-srv ~]# cat a.txt root123 ROot asdf Root_123 rOOtss root 123 [root@MiWiFi-R3-srv ~]# grep -i "root" a.txt root123 ROot asdf Root_123 rOOtss root 123 [root@MiWiFi-R3-srv ~]# grep -w "root" a.txt root 123
grep種類
grep
fgrep
pgrep
egrep
正則介紹
^ 行首
$ 行尾
. 除了換行符之外的任意單個字符
* 前導字符的零個或多個
.* 全部字符
[] 字符組內的任一字符
[^] 對字符組內的每一個字符取反(不匹配字符組內的每一個字符)
^[^] 非字符組內的字符開頭的行
[a-z] 小寫字母
[A-Z] 大寫字母
[a-Z] 小寫和大寫字母
[0-9] 數字
\< 單詞頭 單詞通常以空格或特殊字符作分隔,連續的字符串被當作單詞
\> 單詞尾
擴展正則 sed 加 -r 參數 或轉義
grep 加 -E 或 egrep 或轉義
AWK 直接支持 但不包含{n,m}
可使用--posix支持
[root@MiWiFi-R3-srv ~]# awk '/ro{1,3}/{print}' /etc/passwd
[root@MiWiFi-R3-srv ~]# awk --posix '/ro{1,3}/{print}' /etc/passwd
sed -n '/roo\?/p' /etc/passwd
sed -rn '/roo?/p' /etc/passwd
? 前導字符零個或一個
+ 前導字符一個或多個
abc|def abc或def
a(bc|de)f abcf 或 adef
x\{m\} x出現m次
x\{m,\} x出現m次至屢次(至少m次)
x\{m,n\} x出現m次至n次
posix定義的字符分類
[:alnum:] Alphanumeric characters.
匹配範圍爲 [a-zA-Z0-9]
[:alpha:] Alphabetic characters.
匹配範圍爲 [a-zA-Z]
[:blank:] Space or tab characters.
匹配範圍爲 空格和TAB鍵
[:cntrl:] Control characters.
匹配控制鍵 例如 ^M 要按 ctrl+v 再按回車 才能輸出
[:digit:] Numeric characters.
匹配全部數字 [0-9]
[:graph:] Characters that are both printable and visible. (A space is print-
able, but not visible, while an a is both.)
匹配全部可見字符 但不包含空格和TAB 就是你在文本文檔中按鍵盤上能用眼睛觀察到的全部符號
[:lower:] Lower-case alphabetic characters.
小寫 [a-z]
[:print:] Printable characters (characters that are not control characters.)
匹配全部可見字符 包括空格和TAB
能打印到紙上的全部符號
[:punct:] Punctuation characters (characters that are not letter, digits, con-
trol characters, or space characters).
特殊輸入符號 +-=)(*&^%$#@!~`|\"'{}[]:;?/>.<,
注意它不包含空格和TAB
這個集合不等於^[a-zA-Z0-9]
[:space:] Space characters (such as space, tab, and formfeed, to name a few).
[:upper:] Upper-case alphabetic characters.
大寫 [A-Z]
[:xdigit:] Characters that are hexadecimal digits.
16進制數 [0-f]
使用方法:
[root@seker ~]# grep --color '[[:alnum:]]' /etc/passwd
正則表達式及字符處理 目標文件/etc/passwd,使用grep命令或egrep 1.顯示出全部含有root的行: 2.輸出任何包含bash的全部行,還要輸出緊接着這行的上下各兩行的內容: 3. 顯示出有多少行含有nologin。 4.顯示出那些行含有root,並將行號一塊輸出。 5.顯示出文件中 6.新建用戶 abominable abominate anomie atomize 編寫正則表達式,將他們匹配出來 egrep 'a.omi(nabl|nat|z|)e' /etc/passwd 7.建四個用戶 Alex213sb Wpq2222b yH438PIG egon666 egon 過濾出用戶名組成是字母+數字+字母的行 [root@MiWiFi-R3-srv ~]# egrep '^[a-Z]+[0-9]+[a-Z]+' /etc/passwd 8.顯示出/etc目錄下全部包含root的文件名 9. 過濾掉/etc/ssh/sshd_config內全部註釋和全部空行 grep -v '^#' /etc/ssh/sshd_config |grep -v '^ *$'
sed
流編輯器 stream editer,是以行爲單位的處理程序
sed 流編輯器 stream editer
語法
sed [options] 'command' in_file[s]
options 部分
-n
-e
-i
-f
command 部分
'[地址1,地址2] [函數] [參數(標記)]'
定址的方法 1.數字 2.正則
數字
十進制數
1 單行
1,3 範圍 從第一行到第三行
2,+4 匹配行後若干行
4,~3 從第四行到下一個3的倍數行
2~3 第二行起每間隔三行的行
$ 尾行
1! 除了第一行之外的行
正則
正則必須用//包裹起來
擴展正則須要用 -r 參數或轉義
數字定址:sed -n '1p' /etc/passwd
正則定址:sed -n '/^root/p' /etc/passwd
正則介紹
^ 行首
$ 行尾
. 除了換行符之外的任意單個字符
* 前導字符的零個或多個
.* 全部字符
[] 字符組內的任一字符
[^] 對字符組內的每一個字符取反(不匹配字符組內的每一個字符)
^[^] 非字符組內的字符開頭的行
[a-z] 小寫字母
[A-Z] 大寫字母
[a-Z] 小寫和大寫字母
[0-9] 數字
\< 單詞頭 單詞通常以空格或特殊字符作分隔,連續的字符串被當作單詞
\> 單詞尾
擴展正則 加 -r 參數 或轉義
sed -n '/roo\?/p' /etc/passwd
sed -rn '/roo?/p' /etc/passwd
? 前導字符零個或一個
+ 前導字符一個或多個
abc|def abc或def
a(bc|de)f abcf 或 adef
x\{m\} x出現m次
x\{m,\} x出現m次至屢次(至少m次)
x\{m,n\} x出現m次至n次
函數
增刪改
a 後插
c 替換
i 前插
d 刪除
輸入輸出
p 打印匹配的行 通常和 -n 參數連用,以屏蔽默認輸出
r 從文件中讀入
w 寫入到文件中
控制流
! 命令取反 例: 1!d 刪除第一行之外的行
{} 命令組合 命令用分號分隔 {1h;G} 能夠理解爲 -e 參數的另外一種寫法
= 打印行號(輸入行的號碼,而非處理的次數行號) 例如: sed -n '2{=;p}' infile
n 讀入下一行到模式空間 例:'4{n;d}' 刪除第5行
N 而是追加下一行到模式空間,再把當前行和下一行同時應用後面的命令
替換
s 字符串替換 s/old/new/
$ sed -n 's/root/ABCDEF/p' /etc/passwd
ABCDEF:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/ABCDEF:/sbin/nologin
$ sed -n 's/root/ABCDEF/gp' /etc/passwd
ABCDEF:x:0:0:ABCDEF:/ABCDEF:/bin/bash
operator:x:11:0:operator:/ABCDEF:/sbin/nologin
$ sed -n 's/root/ABCDEF/2p' /etc/passwd
root:x:0:0:ABCDEF:/root:/bin/bash
$ sed -n 's/root/ABCDEF/3p' /etc/passwd
root:x:0:0:root:/ABCDEF:/bin/bash
$ sed -n 's/root/ABCDEF/gp' /etc/passwd
ABCDEF:x:0:0:ABCDEF:/ABCDEF:/bin/bash
operator:x:11:0:operator:/ABCDEF:/sbin/nologin
$
\(\) 保存被匹配的字符 以備反向引用\N時使用 最多9個標籤 標籤順序從左至右
& 替換時使用,在不定義標籤時使用(反向引用)
試作:
刪除第一個單詞
刪除最後一個單詞
將第一個單詞和最後一個單詞兌換位置
y 字符替換(變形)
工做模式 模式空間和保持空間介紹
$ sed '1{p;p}' a.txt
11111111
11111111
11111111
22222222
33333333
44444444
55555555
66666666
$
置換 模式空間和保持空間(暫存空間)
h 把模式空間內容覆蓋到保持空間中
H 把模式空間內容追加到保持空間中
g 把保持空間內容覆蓋到模式空間中
G 把保持空間內容追加到模式空間中
x 交換模式空間與保持空間的內容
# cat test.sh
1111111
2222222
3333333
4444444
# sed '{1h;2,3H;4G}' ./test.sh
1111111
2222222
3333333
4444444
1111111
2222222
3333333
# sed '{1h;2x;3g;$G}' ./test.sh
1111111
1111111
2222222
4444444
2222222
#
試作題
將第一行插入到每一個偶數行的後面
$ sed '1h;0~2G' a.txt
11111111
22222222
11111111
33333333
44444444
11111111
55555555
66666666
11111111
$
顛倒輸出
$ sed '1!G;h;$!d' rev.txt
xyz
def
abc
$
腳本方法
-f 參數 引用腳本(腳本的末尾不能有空格製表符或其餘文本)
# cat sed.sh
2,4d
s/777/seker/
s/999/seker&seker/
# sed -f sed.sh test.txt
1111111
5555555
6666666
seker7777
8888888
seker999seker9999
#
在腳本中指明解釋器爲sed
# cat sed.sh
#!/bin/sed -f
2,4d
s/777/seker/
s/999/seker&seker/
# ./sed.sh test.txt
1111111
5555555
6666666
seker7777
8888888
seker999seker9999
#
高級流控命令 b分支 t測試
分支命令用於無條件轉移,測試命令用於有條件轉移
分支 branch
跳轉的位置與標籤相關聯
若是有標籤則跳轉到標籤所在的後面行繼續執行
若是沒有標籤則跳轉到腳本的結尾處.
標籤 以冒號開始後接標籤名 不要在標籤名先後使用空格
跳轉到標籤指定位置
[root@stu254 ~]# grep seker /etc/passwd
seker:x:500:500::/home/seker:/bin/bash
[root@stu254 ~]#
[root@stu254 ~]# grep seker /etc/passwd |sed ':top;s/seker/blues/;/seker/b top;s/5/555/'
blues:x:55500:500::/home/blues:/bin/bash
[root@stu254 ~]#
命令分析:讓單次替換(cmd1)循環執行,直到條件不知足
:top; 定義一個top標籤
s/seker/blues/; cmd1
/seker/b top; 若是模式匹配則跳轉到top標籤
s/5/555/ 當上一條模式不匹配時,既會繼續執行這一條
選擇執行
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash
[root@stu254 ~]#
zorro:x:501:501::/home/zorro:/bin/bash
[root@stu254 ~]# grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
zorro:x:6665501:501::/home/zorro:/bin/bash
[root@stu254 ~]#
命令分析: 執行cmd1,再去模式匹配,成功則跳轉到cmd3開始執行,不然(模式不匹配)會按命令順序逐個執行
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
:end;
s/5/666/ cmd3
另外一種選擇執行
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash
[root@stu254 ~]# grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
zorro:x:55501:501::/home/zorro:/bin/bash
[root@stu254 ~]#
命令分析: 執行cmd1;模式匹配cmd2成功則執行cmd3;不然執行cmd2,再跳轉到腳本末尾
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
b;
:end;
s/5/666/ cmd3
測試命令,若是前一個替換命令執行成功則跳轉到腳本末尾 (case結構)
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/bash
[root@stu254 ~]# grep 'zorro' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
zorro:x:501:501::/DEF/zorro:/bin/bash
[root@stu254 ~]#
與標籤關聯,跳轉到標籤位置
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/ABC/;t end;s/home/DEF/;t;:end;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/XYZ
[root@stu254 ~]#
[seker@seker ~]$ grep 'zorro' /etc/passwd |sed 's/seker/ABC/;t end;s/home/DEF/;t;:end;s/bash/XYZ/'
zorro:x:501:501::/DEF/zorro:/bin/bash
Sed做業:以/etc/passwd文件爲模板 1,刪除文件每行的第一個字符。 2,刪除文件每行的第二個字符。 3,刪除文件每行的最後一個字符。 4,刪除文件每行的倒數第二個字符。 5,刪除文件每行的第二個單詞。 6,刪除文件每行的倒數第二個單詞。 7,刪除文件每行的最後一個單詞。 8,交換每行的第一個字符和第二個字符。 9,交換每行的第一個字符和第二個單詞。 10,交換每行的第一個單詞和最後一個單詞。 11,刪除一個文件中全部的數字。 12,刪除每行開頭的全部空格。 13,用製表符替換文件中出現的全部空格。 14,把全部大寫字母用括號()括起來。 15,打印每行3次。 16,隔行刪除。 17,把文件從第2行到第5行復制到第7行後面。(選作題) 18,把文件從第2行到第5行移動到第7行後面。(選作題) 19,只顯示每行的第一個單詞。 20,打印每行的第一個單詞和第三個單詞。 21,將格式爲 mm/yy/dd 的日期格式換成 mm;yy;dd 22, a.txt內容 ABC DEF XYZ 經過SED實現tac命令 tac a.txt XYZ DEF ABC 1. sed -r 's/^(.)(.*)/\2/' /etc/passwd 2. sed -r 's/^(.)(.)(.*)/\1\3/' /etc/passwd 3. sed -r 's/(.*)(.)$/\1/' /etc/passwd 4. sed -r 's/(.*)(.)(.)$/\1\3/' /etc/passwd 5. sed -r 's/^([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)/\1\2\4/' /etc/passwd 6. sed -r 's/([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)$/\1\3\4/' /etc/passwd 7. sed -r 's/([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)$/\1\2\3/' /etc/passwd 8. sed -r 's/^(.)(.*)(.)$/\3\2\1/' /etc/passwd 9. sed -r 's/^(.)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)/\4\2\3\1\5/' /etc/passwd 10. sed -r 's/^([a-Z]+)([^a-Z]+)(.*)([^a-Z]+)([a-Z]+)$/\5\2\3\4\1/' /etc/passwd 11. sed -r 's/[0-9]//g' /etc/passwd 12. sed -r 's/^ *//g' /etc/passwd 13. sed -r 's/ /\t/g' /etc/passwd 14. sed -r 's/[A-Z]/(&)/g' /etc/passwd 15. sed 'p;p' /etc/passwd 16. sed '1~2d' /etc/passwd 選作題17-18:文件內容 [root@MiWiFi-R3-srv ~]# cat test 11111111111 2222222222 333333333 4444444444 55555555555 6666666666 777777777777 888888888888 99999999999999 17.sed '2h;3,5H;7G' test 18. sed '2h;3,5H;2,5d;7G' test 19. sed -r 's/^([a-Z]+)([^a-Z]+)(.*)/\1/' /etc/passwd 20. sed -r 's/^([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)/\5\2\3\4\1\6/' /etc/passwd 21. 22. sed -r '{1h;1d;2G;2h;2d;3G;3h}' 23. echo "2012/12/11" |sed -r 's/\//:/g' echo "2012/12/11" |sed -r 's#\/#:#g' echo "2012/12/11" |sed -r 's@\/@:@g'
awk -F: '$1 == "root"{print $1,NR,NF}' /etc/passwd
awk -F: 'NR>20 || NR<3{print $1,$3,$NF}' /etc/passwd
awk -F: 'NR>1 && NR<3{print $1,NR,NF}' /etc/passwd
awk -F: 'NR>1 && NR<4{print $1,NR,NF}' /etc/passwd
awk -F: '$1~/^r/{print $1,NR,NF}' /etc/passwd
awk -F: '/^root/{print $1,NR,NF}' /etc/passwd
username=root
awk -v var=$username -F: '$1 == var{print $1,NR,NF}' /etc/passwd
打印uid在30~40範圍內的用戶名。 打印第5-10行的行號和用戶名 打印奇數行 打印偶數行 打印字段數大於5的行 打印UID不等於GID的用戶名 打印沒有指定shell的用戶
awk詳細
語法
awk [options] 'commands' files
option
-F 定義字段分隔符,默認的分隔符是連續的空格或製表符
使用option中的-F參數定義間隔符號
用$1,$2,$3等的順序表示files中每行以間隔符號分隔的各列不一樣域
NF變量表示當前記錄的字段數
-v 定義變量並賦值 也能夠借用次方式從shell變量中引入
command
讀前處理 行處理 讀後處理
1.讀前處理 BEGIN{awk_cmd1;awk_cmd2}
2.行處理:定址 命令
定址方法: 正則,變量,比較和關係運算
正則須要用//包圍起來
^ 行首
$ 行尾
. 除了換行符之外的任意單個字符
* 前導字符的零個或多個
.* 全部字符
[] 字符組內的任一字符
[^] 對字符組內的每一個字符取反(不匹配字符組內的每一個字符)
^[^] 非字符組內的字符開頭的行
[a-z] 小寫字母
[A-Z] 大寫字母
[a-Z] 小寫和大寫字母
[0-9] 數字
\< 單詞頭 單詞通常以空格或特殊字符作分隔,連續的字符串被當作單詞
\> 單詞尾
擴展正則 加 -r 參數 或轉義
sed -n '/roo\?/p' /etc/passwd
sed -rn '/roo?/p' /etc/passwd
? 前導字符零個或一個
+ 前導字符一個或多個
abc|def abc或def
a(bc|de)f abcf 或 adef
x\{m\} x出現m次
x\{m,\} x出現m次至屢次(至少m次)
x\{m,n\} x出現m次至n次
NR變量定址
NR 表示AWK讀入的行數
FNR表示讀入行所在文件中的行數
# awk '{print NR,FNR,$1}' file1 file2
1 1 aaaaa
2 2 bbbbb
3 3 ccccc
4 1 dddddd
5 2 eeeeee
6 3 ffffff
#
邏輯運算 可直接引用域進行運算
== >= <= != > < ~ !~
# awk 'NR==1 {print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#
3.命令 {print $0}
4.讀後處理 END {awk_cmd1;awk_cmd2;}
AWK變量
NR 當前記錄的個數(所有文件鏈接後的統計)
FNR 當前記錄的個數(僅爲當前文件的統計,非所有)
FS 字段分隔符 默認爲連續空格或製表符,可使用多個不一樣的符號作分隔符 -F[:/]
OFS 輸出字符的分隔符 默認是空格
# awk -F: 'OFS="=====" {print $1,$2}' /etc/passwd
root=====x
NF 當前讀入行的字段個數
ORS 輸出記錄分隔符 默認是換行
# awk -F: 'ORS="=====" {print $1,$2}' /etc/passwd
root x=====bin x=====
FILENAME 當前文件名
引用shell變量的方法
# a=root
# awk -v var=$a -F: '$1 == var {print $0}' /etc/passwd
或者 把整個命令拆開傳遞,讓shell變量外露,
# awk -F: '$1 == "'$a'" {print $0}' /etc/passwd
# a=NF
# awk -F: '{print $'$a'}' /etc/passwd
操做符
賦值
= += -= /= *=
邏輯與 邏輯或 邏輯非
&& || !
匹配正則或不匹配,正則須要用 /正則/ 包圍住
~ !~
關係 比較字符串時要把字符串用雙引號引發來
< <= > >= != ==
字段引用
$ 字段引用須要加$,而變量引用直接用變量名取
運算符
+ - * / % ++ --
轉義序列
\\ \自身
\$ 轉義$
\t 製表符
\b 退格符
\r 回車符
\n 換行符
\c 取消換行
練習
打印uid在30~40範圍內的用戶名。
打印第5-10行的行號和用戶名
打印奇數行
打印偶數行
打印字段數大於5的行
打印UID不等於GID的用戶名
打印沒有指定shell的用戶
打印1..1000之內的7的倍數和包含7的數
流程控制
分支結構
if (條件) 動做
如有多個動做,則要用大括號將動做體包含起來 if (條件) {動做1;動做2}
# awk -F: '{if ($1 == "root") print $1}' /etc/passwd
root
#
# awk -F: '{if ($1 == "root") {print $1;print $6}}' /etc/passwd
root
/root
#
if (條件1)
動做1
else
動做2
# awk -F: '{if ($1 == "root"){print $1}else print $6}' /etc/passwd
# awk -F: '{if ($1 == "root") print $1;else print $6}' /etc/passwd
上面兩個命令是等價的,要麼用分號隔開,表示第一個動做體的結束,要麼將動做體用大括號定位範圍
if (條件 1)
動做1
else if(條件 2)
動做2
else if(條件 3)
動做3
else
動做4
# awk -F: '{if ($1 == "root") print $1;else if ($1 == "seker") print $6;else if ($1 == "zorro") print $7;else print NR}' /etc/passwd
root
2
3
...
33
/home/seker
/bin/bash
36
條件 ? 動做1 : 動做2
expr?action1:action2
# awk -F: 'var=($3 >= 500)?$1:"system_user" {print $1"\t"$3"\t"var}' /etc/passwd
# awk -F: '{print ($3>500?$1:$2)}' /etc/passwd
練習
將系統用戶按UID分組標記 0 admin; 1-499 sysuser; 500+ users
awk -F: '{if($3==0) print $1"\t"$3"\t""admin";else if($3>=1&&$3<500) print $1,$3,"sysuser";else print $1,$3,"user"}' /etc/passwd
輸出樣式
%s是字符類型,%d數值類型
printf默認是不輸出換行的因此要加\n
10和7是偏移量
默認是右對齊,全部加個- 就是左對齊,就是把不足的位數用空格填充
注意:格式與輸出列之間要有逗號
# awk -F: '{printf "%-10s %-10d %s\n",$1,$3,$7}' /etc/passwd
讀前處理和讀後處理
# awk -F: 'BEGIN{i=1} {i++} END {print i}' /etc/passwd
47
#
# awk -F: 'BEGIN {print NR,NF}' /etc/passwd
0 0
#
# awk -F: 'END {print NR,NF}' /etc/passwd
46 7
#
練習
找出普通用戶的用戶名並統計數量
# awk -F: 'BEGIN{i=0} $3 >= 500 {print $1;i++} END {print i}' /etc/passwd
計算UID相加的總和;計算GID相加的總和
# awk -F: 'BEGIN{i=0}{sum+=$3;i++}END{print i;print sum}' /etc/passwd
# awk -F: 'BEGIN{i=0}{sum+=$3;gsum+=$4;i++}END{print i;print sum;print gsum}' /etc/passwd
計算VSZ和RSS各自的和 並以M單位顯示
# ps aux | awk 'BEGIN{i=0}NR>=2{sum+=$5;i++}END{print sum/1024"M"}'
# ps aux | awk 'BEGIN{i=0}NR>=2{vsum+=$5;rsum+=$6;i++}END{print vsum/1024"M";print rsum/1024"M";print i}'
循環語句
while(條件) {
動做
條件運算
}
# awk -F: '{while($3<3) {print $3,$1;$3++}}' /etc/passwd
0 root
1 root
2 root
1 bin
2 bin
2 daemon
#
BEGIN塊能夠獨立使用,不須要引入文件
# awk 'BEGIN{i=1;while(i<100) {print i;i++}}'
練習
打印100之內的偶數
# awk 'BEGIN{i=1;while(i<100) {if (i%2==0) print i;i++}}'
x=1
do {
動做1
x++
} while (x<5)
# awk 'BEGIN{i=5;do{print i;i++}while(i<10)}'
# awk 'BEGIN{i=5;do{print i;i++}while(i<1)}'
for(預置;條件;遞增) {
動做
}
# awk 'BEGIN {for (x=1;x<=4;x++) print x }'
1
2
3
4
#
# awk 'BEGIN{for (i=1;i<=4;i++) {for (j=1;j<=4;j++) print i,j}}'
練習
使用嵌套的for循環,打印100-999之間的數,個十百位分別用一個for來打印
# awk 'BEGIN{OFS="";for (i=1;i<=9;i++) {for (j=0;j<=9;j++) {for (n=0;n<=9;n++) print i,j,n}}}'
打印乘法口訣表
# cat 99.sh
#!/bin/bash
awk 'BEGIN{
for(i=1;i<10;i++)
{
for(j=1;j<=i;j++)
printf "%d*%d=%d ",j,i,j*i
print
}
}'
#
打印金字塔
# cat jin.sh
#!/bin/bash
awk 'BEGIN{
num=5
for(i=1;i<=num;i++)
{
for (n=1;n<=num-i;n++)
printf "%s"," "
for (j=1;j<=2*i-1;j++)
printf "%s","*"
print
}
}'
#
逆序輸出每一個字段
達到這樣既可
/bin/bash
/root
root
0
0
x
root
# awk -F: '{for (x=NF;x>0;x--) print $x}' /etc/passwd
繼續解決上一個試作題的格式問題
# awk -F: '/bash$/{for (x=NF;x>0;x--) printf "%-13s",$x;printf "\n"}' /etc/passwd
跳轉語句
break 跳出循環
# awk 'BEGIN {for(x=1;x<5;x++) {if (x==3) break;print x }}'
1
2
continue 在達到循環底部以前終止當前循環 重新開始下一次循環
# awk 'BEGIN {for(x=1;x<5;x++) {if (x==3) continue;print x }}'
1
2
4
next 讀入下一行 同時返回腳本頂部 這樣能夠避免對當前行執行其餘操做
# awk -F: 'NR > 5 {next} {print $1} END {print NR}' /etc/passwd
root
bin
daemon
adm
lp
46
#
exit 使讀取動做終止 並將控制移動到END,若是沒有END則終止腳本
# awk -F: 'NR > 5 {exit} {print $1} END {print NR}' /etc/passwd
root
bin
daemon
adm
lp
6
#
數組
自定義數組
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";print ary[1],ary[2]}'
seker zorro
#
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";for(i in ary) print ary[i]}'
seker
zorro
#
刪除一個元素 對元素給空值並不能清除這個元素 要想清除一個元素須要使用delete ary[idx]
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";ary[3]="blues";ary[2]="";for(i in ary) print ary[i]}'
seker
blues
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";ary[3]="blues";delete ary[2];for(i in ary) print ary[i]}'
seker
blues
#
循環產生數組和取出數組
# awk 'BEGIN{n=5;for (i=1;i<=n;i++) ary[i]=i+100;for(m in ary) print m,ary[m]}'
4 104
5 105
1 101
2 102
3 103
#
# awk -F: '{ary[NR]=$1} END {for(i in ary) print i,ary[i]}' /etc/passwd
1 root
2 bin
3 daemon
4 adm
5 lp
6 sync
7 shutdown
8 halt
9 mail
# awk -F: '{ary[$3]=$1} END {for(i in ary) print i,ary[i]}' /etc/passwd
10 uucp
11 operator
12 games
13 gopher
14 ftp
32 rpc
37 rpm
ARGV 命令行中參數數組
# awk '{for (i in ARGV) {print i,ARGV[i]}}' /etc/passwd /etc/fstab
0 awk
1 /etc/passwd
2 /etc/fstab
#### i 爲下標; ARGV[i] 下標爲i的值
練習
統計每種shell被使用的次數
函數
算術函數 int
[root@stu254 ~]# awk 'BEGIN {print int(3.9415)}'
3
[root@stu254 ~]#
隨機數函數 rand() srand()
rand() 取值 0 > r < 1 之間 默認的種子是系統時間 精確到秒
srand()取值 0 > r < 1 之間 能夠指定種子來影響rand()取值數 默認是系統時間 精確到秒
[root@stu254 ~]# awk 'BEGIN {srand(222);print int(rand()*100000000)}'
90204196
[root@stu254 ~]#
字符串函數
substr(s,x[,y])
返回字符串s中從位置x起至y的子串,若是沒有給出y,則從x開始到結束.
[root@stu254 ~]# awk 'BEGIN {x="abcdefxyz";print substr(x,4,3)}'
def
[root@stu254 ~]#
大寫小寫
sprintf() 自己並不能打印,作格式轉換,將數字轉換成ASCII字符
# awk 'BEGIN {for(i=97;i<=122;++i) print tolower(toupper(sprintf("%c",i)))}'
字符串長度
length() 若是沒有給定字符串則使用$0
[root@stu254 ~]# awk 'BEGIN {print length("abcdefxyz")}'
9
gsub(/abc/,"ABC",x) 全局字符串替換
從x中用匹配的abc正則替換成ABC
[root@stu254 ~]# awk 'BEGIN {x="xyzabcxyzabcxyz";gsub(/abc/,"ABC",x);print x}'
xyzABCxyzABCxyz
[root@stu254 ~]# sub 第一次的替換
[root@stu254 ~]# awk 'BEGIN {x="xyzabcxyzabcxyz";sub(/abc/,"ABC",x);print x}'
xyzABCxyzabcxyz
[root@stu254 ~]#
gensub(r, s, h [, t]) Search the target string t for matches of the reg-
ular expression r. If h is a string beginning
with g or G, then replace all matches of r with s.
Otherwise, h is a number indicating which match of
r to replace. If t is not supplied, $0 is used
instead.
gensub(正則,替換,範圍,目標串)
[root@tch254 ~]# awk 'BEGIN{print gensub("zorro","AAAA","2","seker zorro zorro seker")}'
seker zorro AAAA seker
[root@tch254 ~]# echo seker zorro zorro seker | sed 's/zorro/AAAA/2'
seker zorro AAAA seker
[root@tch254 ~]#
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","g");print}'
seker AAAA AAAA seker
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","2");print}'
seker zorro AAAA seker
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","h");print}'
seker AAAA zorro seker
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","1");print}'
seker AAAA zorro seker
[root@tch254 ~]#
系統函數
getline
交互輸入
[root@stu254 ~]# awk -F: 'BEGIN {printf "Enter Number: ";getline ;for(i=1;i<=$0;i++) print i}'
Enter Number: 3
1
2
3
[root@stu254 ~]#
將輸入賦值給變量
[root@stu254 ~]# awk -F: 'BEGIN {printf "Enter Number: ";getline NUM;for(i=1;i<=NUM;i++) print i}'
Enter Number: 3
1
2
3
[root@stu254 ~]#
從文件中讀入
[root@tch254 ~]# awk -F: 'BEGIN {getline < "/etc/passwd" ; print $3"\t"$1}'
0 root
[root@tch254 ~]#
#awk -F: 'BEGIN {while (getline < "/etc/passwd" > 0) print $3"\t"$1}'
getline < "/etc/passwd" 從文件中讀入,每次讀取一行,默認狀況下讀取的次數等於awk自身引入文件的行數
也能夠放到for中來控制讀取的次數
> 0 測試讀取的返回值,成功返回1,失敗返回-1,0文件末尾
從命令輸出中輸入
[root@stu254 ~]# awk 'BEGIN {"uname -a"|getline ;print $3}'
2.6.18-53.el5
[root@stu254 ~]#
system(command)
系統命令要用""引發來
[root@stu254 ~]# rm -rf abc/
[root@stu254 ~]# awk 'BEGIN {if(system("mkdir abc") != 0 ) print "ERR"}'
[root@stu254 ~]# awk 'BEGIN {if(system("mkdir abc") != 0 ) print "ERR"}'
mkdir: 沒法建立目錄 「abc」: 文件已存在
ERR
[root@stu254 ~]#
[root@tch254 ~]# awk 'BEGIN {if(system("mkdir abc 2>/dev/null") != 0 ) print "ERR"}'
ERR
[root@tch254 ~]#
awk腳本的介紹 -f 與 #!/bin/awk -f
使用awk添加系統用戶
[root@mail ~]# cat useradd.awk
#!/bin/awk -f
{
system("useradd "$1";echo "$2"|passwd --stdin "$1)
}
[root@mail ~]# cat username
myname 1234
[root@mail ~]#
[root@mail ~]# ./useradd.awk ./username
Changing password for user myname.
passwd: all authentication tokens updated successfully.
[root@mail ~]#
1.使用:或/符號作分隔符,將字段逆序輸出/etc/passwd文件的每行 2. # awk -F: 'NR < 11 {print $3,$1}' /etc/passwd > name.txt # awk -F: 'NR < 11 {print $3,$6}' /etc/passwd > home.txt # join name.txt home.txt 觀察兩個文件,以及join命令輸出,用awk引入name.txt,home.txt兩個文件,模擬joni命令的輸出 3.統計/etc/passwd中每種shell的被使用人數 輸出格式: counts shell 1 1 /bin/sync 4 /bin/bash 31 /sbin/nologin 1 /sbin/halt 1 /sbin/shutdown 4.統計ps中RSZ,VSS各自總和 輸出格式: ps MEM statistic VSZ_SUM : 164.277M RSS_SUM : 47.8555M 5.計算/etc/passwd中全部用戶的UID平均數,以及GID平均數. 輸出格式: UID and GID AVG UID-AVG : 1750.72 GID_AVG : 1754 6. 根據uid值給用戶分等級 Admin system users 輸出格式: LEVEL NAME Admin root sysuser bin users seker admin_count: N sys_user_count: N users_count: N 7. 分別用GREP,SED,AWK將ifconfig中匹配到eth1的網卡全部信息打印出來. 8. SHELL實現批量創建多個文件,將文件拓展名加上.txt,再加上.doc,再把中間的.txt去掉 9. AWK腳本實現間隔五行打印表頭 [root@mail ~]# ./awk_print.sh /etc/passwd Username Uid root 0 bin 1 daemon 2 adm 3 lp 4 Username Uid shutdown 6 halt 7 mail 8 news 9 uucp 10 10.用$RANDOM產生100個隨機數,交給AWK產生數組,在數組內部排序,最後輸出.(禁止用sort命令) 11. 創建 aa.txt 文本 # cat aa.txt aaa/bbb/ccc ddd/eee/fff ggg/hhh/iii aaa/bbb/ccc/aaa/bbb/ccc/ddd/eee # 用AWK或SED輸出以下格式 ccc aaa/bbb/ fff ddd/eee/ iii ggg/hhh/ eee aaa/bbb/ccc/aaa/bbb/ccc/ddd/ 12. 創建 a.txt b.txt 文件 [root@tch254 ~]# cat a.txt 1 a 2 b 3 c 4 d 5 e 6 f 7 g [root@tch254 ~]# cat b.txt 5 ABC 3 DEF 4 XYZ [root@tch254 ~]# 使用AWK處理兩個文件輸出以下結果 e ABC c DEF d XYZ [root@tch254 ~]#
11111111111 2222222222 333333333 4444444444 55555555555 aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa 99999999999999 99999999999999 99999999999999 99999999999999 99999999999999 99999999999999 99999999999999 aaaaaaaaaa 6666666666 777777777777 888888888888 aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa 99999999999999 aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa aaaaaaaaaa
[root@MiWiFi-R3-srv ~]# cat test |sort |uniq #排序去重
11111111111
2222222222
333333333
4444444444
55555555555
6666666666
777777777777
888888888888
99999999999999
aaaaaaaaaa
[root@MiWiFi-R3-srv ~]# cat /etc/passwd |cut -d: -f2
[root@MiWiFi-R3-srv ~]# find / -size +2M -type f -name \*.txt