第五週小總結

for 變量名 in 列表;do
循環體
done
執行機制:
依次將列表中的元素賦值給“變量名”; 每次賦值後即執行一次循環體; 直到列表中的元素耗盡,循環結束

for循環
列表生成方式:
(1) 直接給出列表
(2) 整數列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:.sh
(5) 變量引用
$@, $

for特殊格式
雙小括號方法,即((…))格式,也可以用於算術運算
雙小括號方法也可以使bash Shell實現C語言風格的變量操作
I=10
((I++))
for循環的特殊格式:
for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))
do
循環體
done
控制變量初始化:僅在運行到循環代碼段時執行一次
控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,而後再做條件判斷

while循環
while CONDITION; do
循環體
done
CONDITION:循環控制條件;進入循環之前,先做一次判斷;每一次循環之後會再次做判斷;條件爲“true”,則執行一次循環;直到條件測試狀態爲“false”終止循環
因此:CONDTION一般應該有循環控制變量;而此變量的值會在循環體不斷地被修正
進入條件:CONDITION爲true
退出條件:CONDITION爲false

until循環
until CONDITION; do
循環體
done
進入條件: CONDITION 爲false
退出條件: CONDITION 爲true

循環控制語句continue
用於循環體中
continue [N]:提前結束第N層的本輪循環,而直接進入下一輪判斷;最內層爲第1層
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done

循環控制語句break
用於循環體中
break [N]:提前結束第N層循環,最內層爲第1層
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done

循環控制shift命令
shift [n]
用於將參量列表 list 左移指定次數,缺省爲左移一次。
參量列表 list 一旦被移動,最左端的那個參數就從列表中刪除。while 循環遍歷位置參量列表時,常用到 shift
./doit.sh a b c d e f g h
./shfit.sh a b c d e f g h

示例:doit.sh
#!/bin/bash

Name: doit.sh

Purpose: shift through command line arguments

Usage: doit.sh [args]

while [ $# -gt 0 ] # or (( $# > 0 ))
do
echo $*
shift
done

示例:shift.sh
#!/bin/bash
#step through all the positional parameters
until [ -z "$1" ]
do
echo "$1"
shift
done
echo

創建無限循環
while true; do
循環體
done
until false; do
循環體
Done

特殊用法
while循環的特殊用法(遍歷文件的每一行)
while read line; do
循環體
done < /PATH/FROM/SOMEFILE
依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line
練習
掃描/etc/passwd文件每一行,如發現GECOS字段爲空,則將用戶名和單位電話爲62985600填充至GECOS字段,並提示該用戶的GECOS信息修改成功

select循環與菜單
select variable in list
do
循環體命令
done
select 循環主要用於創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,並顯示 PS3 提示符,等待用戶輸入
用戶輸入菜單列表中的某個數字,執行相應的命令
用戶輸入被保存在內置變量 REPLY 中
select 是個無限循環,因此要記住用 break 命令退出循環,或用 exit 命令終止腳本。也可以按 ctrl+c 退出循環
select 經常和 case 聯合使用
與 for 循環類似,可以省略 in list,此時使用位置參量

定義函數
函數由兩部分組成:函數名和函數體
help function
語法一:
f_name (){
...函數體...
}
語法二:
function f_name {
...函數體...
}
語法三:
function f_name () {
...函數體...
}

函數使用
函數的定義和使用:
可在交互式環境下定義函數
可將函數放在腳本文件中作爲它的一部分
可放在只包含函數的單獨文件中
調用:函數只有被調用纔會執行
調用:給定函數名
函數名出現的地方,會被自動替換爲函數代碼
函數的生命週期:被調用時創建,返回時終止

函數返回值
函數有兩種返回值:
函數的執行結果返回值:
(1) 使用echo等命令進行輸出
(2) 函數體中調用命令的輸出結果
函數的退出狀態碼:
(1) 默認取決於函數中執行的最後一條命令的退出狀態碼
(2) 自定義退出狀態碼,其格式爲:
return 從函數中返回,用最後狀態命令決定返回值
return 0 無錯誤返回
return 1-255 有錯誤返回

在腳本中定義及使用函數
函數在使用前必須定義,因此應將函數定義放在腳本開始部分,直至shell首次發現它後才能使用
調用函數僅使用其函數名即可
示例:
cat func1
#!/bin/bash

func1

hello()
{
echo "Hello there today's date is date +%F"
}
echo "now going to the function hello"
hello
echo “back from the function”

創建函數文件
函數文件示例:
cat functions.main
#!/bin/bash
#functions.main
findit()
{
if [ $# -lt 1 ] ; then
echo "Usage:findit file"
return 1
fi
find / -name $1 –print
}

檢查載入函數
使用set命令檢查函數是否已載入。set命令將在shell中顯示所有的載入函數
示例:
set
findit=( )
{
if [ $# -lt 1 ]; then
echo "usage :findit file";
return 1
fi
find / -name $1 -print
}

行shell函數
要執行函數,簡單地鍵入函數名即可
示例:
findit groups
/usr/bin/groups
/usr/local/backups/groups.bak

刪除shell函數
現在對函數做一些改動後,需要先刪除函數,使其對shell不可用。使用unset命令完成刪除函數
命令格式爲:
unset function_name
示例:
unset findit
再鍵入set命令,函數將不再顯示
環境函數
使子進程也可使用
聲明:export -f function_name
查看:export -f 或 declare -xf

函數參數
函數可以接受參數:
傳遞參數給函數:調用函數時,在函數名後面以空白分隔給定參數列表即可;例如“testfunc arg1 arg2 ...”
在函數體中當中,可使用$1, $2, ...調用這些參數;還可以使用$@, $*, $#等特殊變量

函數變量
變量作用域:
環境變量:當前shell和子shell有效
本地變量:只在當前shell進程有效,爲執行腳本會啓動專用子shell進程;因此,本地變量的作用範圍是當前shell腳本程序文件,包括腳本中的函數
局部變量:函數的生命週期;函數結束時變量被自動銷燬
注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量
在函數中定義局部變量的方法
local NAME=VALUE

函數遞歸示例
函數遞歸:
函數直接或間接調用自身
注意遞歸層數
遞歸實例:
階乘是基斯頓·卡曼於 1808 年發明的運算符號,是數學術語,一個正整數的階乘(factorial)是所有小於及等於該數的正整數的積,並且有0的階乘爲1,自然數n的階乘寫作n!
n!=1×2×3×...×n
階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n
n!=n(n-1)(n-2)...1
n(n-1)! = n(n-1)(n-2)!

函數遞歸示例
示例:fact.sh
#!/bin/bash

fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
fact $1

fork×××
fork×××是一種惡意程序,它的內部是一個不斷在fork進程的無限循環,實質是一個簡單的遞歸程序。由於程序是遞歸的,如果沒有任何限制,這會導致這個簡單的程序迅速耗盡系統裏面的所有資源
函數實現
:(){ :|:& };:
bomb() { bomb | bomb & }; bomb
腳本實現
cat Bomb.sh
#!/bin/bash

./$0|./$0&

信號捕捉trap
trap '觸發指令' 信號
進程收到系統發出的指定信號後,將執行自定義指令,而不會執行原操作
trap '' 信號
忽略信號的操作
trap '-' 信號
恢復原信號的操作
trap -p
列出自定義信號操作
trap finish EXIT
當腳本退出時,執行finish函數

trap示例
#!/bin/bash
trap 'echo “signal:SIGINT"' int
trap -p
for((i=0;i<=10;i++))
do
sleep 1
echo $i
done
trap '' int
trap -p
for((i=11;i<=20;i++))
do
sleep 1
echo $i
done
trap '-' int
trap -p
for((i=21;i<=30;i++))
do
sleep 1
echo $i
done

數組
變量:存儲單個元素的內存空間
數組:存儲多個元素的連續的內存空間,相當於多個變量的集合
數組名和索引
索引:編號從0開始,屬於數值索引
注意:索引可支持使用自定義的格式,而不僅是數值格式,即爲關聯索引,bash4.0版本之後開始支持
bash的數組支持稀疏格式(索引不連續)
聲明數組:
declare -a ARRAY_NAME
declare -A ARRAY_NAME 關聯數組
注意:兩者不可相互轉換

數組賦值
數組元素的賦值
(1) 一次只賦值一個元素
ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"
(2) 一次賦值全部元素
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
(3) 只賦值特定元素
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
(4) 交互式數組值對賦值
read -a ARRAY
顯示所有數組:declare -a

引用數組br/>引用數組元素
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下標爲0的元素
引用數組所有元素
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
數組的長度(數組中元素的個數)
br/>${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
刪除數組中的某元素:導致稀疏格式
unset ARRAY[INDEX]
刪除整個數組
unset ARRAY

數組數據處理br/>引用數組中的元素:
數組切片:
${ARRAY[@]:offset:number}
offset 要跳過的元素個數
number 要取出的元素個數
取偏移量之後的所有元素 ${ARRAY[@]:offset}
向數組中追加元素:
ARRAY[${#ARRAY[*]}]=value
關聯數組:
declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)
注意:關聯數組必須先聲明再調用

示例
生成10個隨機數保存於數組中,並找出其最大值和最小值
#!/bin/bash
declare -i min max
declare -a nums
for ((i=0;i<10;i++));do
nums[$i]=$RANDOM
[ $i -eq 0 ] && min=${nums[$i]} && max=${nums[$i]}&& continue
[ ${nums[$i]} -gt $max ] && max=${nums[$i]}
[ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo “All numbers are ${nums[*]}”
echo Max is $max
echo Min is $min

示例
編寫腳本,定義一個數組,數組中的元素對應的值是/var/log目錄下所有以.log結尾的文件;統計出其下標爲偶數的文件中的行數之和
#!/bin/bash
#
declare -a files
files=(/var/log/.log)
declare -i lines=0
for i in $(seq 0 $[${#files[
]}-1]); do
if [ $[$i%2] -eq 0 ];then
let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
fi
done
echo "Lines: $lines."

字符串切片
${#var}:返回字符串變量var的長度
${var:offset}:返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,到最後的部分,offset的取值在0 到 ${#var}-1 之間(bash4.2後,允許爲負值)
${var:offset:number}:返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,長度爲number的部分
${var: -length}:取字符串的最右側幾個字符
注意:冒號後必須有一空白字符
${var:offset:-length}:從最左側跳過offset字符,一直向右取到距離最右側lengh個字符之前的內容
${var: -length:-offset}:先從最右側向左取到length個字符開始,再向右取到距離最右側offset個字符之間的內容
注意:-length前空格

字符串處理
基於模式取子串
${var#word}:其中word可以是指定的任意字符
功能:自左而右,查找var變量所存儲的字符串中,第一次出現的word, 刪除字符串開頭至第一次出現word字符串(含)之間的所有字符
${var##
word}:同上,貪婪模式,不同的是,刪除的是字符串開頭至最後一次由word指定的字符之間的所有內容
示例:
file=“var/log/messages”
${file#/}: log/messages
${file##
/}: messages

字符串處理
${var%word}:其中word可以是指定的任意字符
功能:自右而左,查找var變量所存儲的字符串中,第一次出現的word, 刪除字符串最後一個字符向左至第一次出現word字符串(含)之間的所有字符
file="/var/log/messages"
${file%/
}: /var/log
${var%%word}:同上,只不過刪除字符串最右側的字符向左至最後一次出現word字符之間的所有字符
示例:
url=http://www.magedu.com:80
${url##
:} 80
${url%%:*} http

字符串處理
查找替換
${var/pattern/substr}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替換之
${var//pattern/substr}: 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替換之
${var/#pattern/substr}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替換之
${var/%pattern/substr}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替換之

字符串處理
查找並刪除
${var/pattern}:刪除var表示的字符串中第一次被pattern匹配到的字符串
${var//pattern}:刪除var表示的字符串中所有被pattern匹配到的字符串
${var/#pattern}:刪除var表示的字符串中所有以pattern爲行首匹配到的字符串
${var/%pattern}:刪除var所表示的字符串中所有以pattern爲行尾所匹配到的字符串
字符大小寫轉換
${var^^}:把var中的所有小寫字母轉換爲大寫
${var,,}:把var中的所有大寫字母轉換爲小寫

變量賦值

高級變量用法-有類型變量
Shell變量一般是無類型的,但是bash Shell提供了declare和typeset兩個命令用於指定變量的類型,兩個命令是等價的
declare [選項] 變量名
-r 聲明或顯示只讀變量
-i 將變量定義爲整型數
-a 將變量定義爲數組
-A 將變量定義爲關聯數組
-f 顯示已定義的所有函數名及其內容
-F 僅顯示已定義的所有函數名
-x 聲明或顯示環境變量和函數
-l 聲明變量爲小寫字母 declare –l var=UPPER
-u 聲明變量爲大寫字母 declare –u var=lower

eval命令
eval命令將會首先掃描命令行進行所有的置換,然後再執行該命令。該命令適用於那些一次掃描無法實現其功能的變量.該命令對變量進行兩次掃描
示例:
[root@server ~]# CMD=whoami
[root@server ~]# echo $CMD
whoami
[root@server ~]# eval $CMD
root
[root@server ~]# n=10
[root@server ~]# echo {0..$n}
{0..10}
[root@server ~]# eval echo {0..$n}
0 1 2 3 4 5 6 7 8 9 10

間接變量引用
如果第一個變量的值是第二個變量的名字,從第一個變量引用第二個變量的值就稱爲間接變量引用
variable1的值是variable2,而variable2又是變量名,variable2的值爲value,間接變量引用是指通過variable1獲得變量值value的行爲
variable1=variable2
variable2=value

間接變量引用
bash Shell提供了兩種格式實現間接變量引用
eval tempvar=\$$variable1
tempvar=${!variable1}
示例:
[root@server ~]# N=NAME
[root@server ~]# NAME=wangxiaochun
[root@server ~]# N1=${!N}
[root@server ~]# echo $N1
wangxiaochun
[root@server ~]# eval N2=\$$N
[root@server ~]# echo $N2
wangxiaochun

創建臨時文件
mktemp命令:創建並顯示臨時文件,可避免衝突
mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filenameXXX
X至少要出現三個
OPTION:
-d: 創建臨時目錄
-p DIR或--tmpdir=DIR:指明臨時文件所存放目錄位置
示例:
mktemp /tmp/testXXX
tmpdir=mktemp –d /tmp/testdirXXX
mktemp --tmpdir=/testdir testXXXXXX

安裝複製文件
install命令:
install [OPTION]... [-T] SOURCE DEST 單文件
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...創建空目錄
選項:
-m MODE,默認755
-o OWNER
-g GROUP
示例:
install -m 700 -o wang -g admins srcfile desfile
install –m 770 –d /testdir/installdir

expect命令
expect 語法:
expect [選項] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
選項
-c:從命令行執行expect腳本,默認expect是交互地執行的
示例:expect -c 'expect "\n" {send "pressed enter\n"}
-d:可以輸出輸出調試信息
示例:expect -d ssh.exp
expect中相關命令
spawn 啓動新的進程
send 用於向進程發送字符串
expect 從進程接收字符串
interact 允許用戶交互
exp_continue 匹配多個字符串在執行動作後加此命令

expect
expect最常用的語法(tcl語言:模式-動作)
單一分支模式語法:
expect “hi” {send “You said hi\n"}
匹配到hi後,會輸出“you said hi”,並換行
多分支模式語法:
expect "hi" { send "You said hi\n" } \
"hehe" { send "Hehe yourself\n" } \
"bye" { send "Good bye\n" }
匹配hi,hello,bye任意字符串時,執行相應輸出。等同如下:
expect {
"hi" { send "You said hi\n"}
"hehe" { send "Hehe yourself\n"}
"bye" { send " Good bye\n"}
}

示例
#!/usr/bin/expect
spawn scp /etc/fstab 192.168.8.100:/app
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
expect eof

示例
#!/usr/bin/expect
spawn ssh 192.168.8.100
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
interact
#expect eof

示例:變量
#!/usr/bin/expect
set ip 192.168.8.100
set user root
set password magedu
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact

示例:位置參數
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
#./ssh3.exp 192.168.8.100 root magedu

示例:執行多個命令
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd haha\n" }
expect "]#" { send "echo magedu |passwd --stdin haha\n" }
send "exit\n"
expect eof
#./ssh4.exp 192.168.8.100 root magedu

示例:shell腳本調用expect
#!/bin/bash
ip=$1
user=$2
password=$3
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd hehe\n" }
expect "]#" { send "echo magedu |passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
#./ssh5.sh 192.168.8.100 root magedu

awk

選項:
-F “分隔符”知名輸入時用到的字段分隔符
-v var=value 變量賦值

分隔符,域和記錄
~ awk執行時,由分隔符分隔的字段段(域)標記$1,$2...$n稱爲域標識。$0爲所有域,注意:此時和shell中變量$符含義不同
•文件的每一行稱爲記錄
•省略action,則默認執行 print $0 的操作

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

awk
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

awk變量
自定義變量(區分字符大小寫)
(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

awk PATTERN
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
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{}:僅在文本處理完成之後執行一次

示例
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”}}’

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)}; i++}}’ /etc/grub2.cfg

awk控制語句
do-while循環
語法:do {statement;…}while(condition)
意義:無論真假,至少執行一次循環體
示例:
awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}’

awk控制語句
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)

awk控制語句
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}'

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:
•(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

awk數組
若要遍歷數組中的每個元素,要使用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

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]):對t字符串進行搜索r表示的模式匹配的內容,並全部替換爲s所表示的內容
echo "2008:08:08 08:08:08" | awk ‘gsub(/:/,“-",$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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章