shell+中sum的用法_shell高级用法
1.if語句
1.1.回顧
在運行腳本前,我們一般先對腳本的語法進行檢查,如果腳本有bug,我們再調試腳本;
(1)語法檢查:bash -n 腳本路徑
(2)腳本調試:bash -x 腳本路徑
1.2.過程式編程語言的執行流程
順序執行
選擇執行
循環執行
選擇執行
1.2.1.&&,||
command1 && command2:如果command1正確,也執行command2;如果command1不正確,不執行command2
command1 || command2:如果command1正確,不執行command2;如果command1不正確,執行command2
1.2.2.if語句
if單分支語句;
if多分支語句
if嵌套語句
(1)if 多分支語句格式(注意:多個分支只會執行一個,執行首先為真的分支)
if [ 條件1 ];then
條件1為真執行這里的代碼
elif [ 條件2 ];then
條件2為真執行這里的代碼
elif [ 條件3 ];then
條件3為真執行這里的代碼
......
elif [ 條件n ];then
條件n為真執行這里的代碼
else
如果所有的條件都不滿足時,執行這里的代碼
fi
(2)if嵌套語句格式
if [ 條件 ];then
if [ 條件 ];then
執行這里的代碼
fi
fi
if [ 條件 ];then
if [ 條件 ];then
執行這里的代碼
fi
else
if [ 條件 ];then
執行這里的代碼
fi
fi
1.3.示例
1.通過腳本參數傳遞一個文件路徑給腳本,判斷此文件的類型;
#!/bin/bash
#
if [ $# -lt 1 ];then
echo "A argument is needed."
exit 1
fi
if ! [ -e $1 ];then
echo "No such file or directory."
exit 2
fi
if [ -f $1 ];then
echo "Common file"
elif [ -d $1 ];then
echo "Directory"
elif [ -L $1 ];then
echo "Symbolic link"
elif [ -b $1 ];then
echo "block special file"
elif [ -c $1 ];then
echo "character special file"
elif [ -S $1 ];then
echo "Socket file"
else
echo "Unknow"
fi
2.寫一個腳本
(1)傳遞一個參數給腳本,此參數為用戶名 ;
(2)根據其ID號來判斷用戶類型:0:管理員 ,1-499:系統用戶,500+:為登入用戶, 輸出用戶是那種類型的用戶;
#!/bin/bash
#(1)傳遞一個參數給腳本,此參數為用戶名
# (2)根據其ID號來判斷用戶類型:0:管理員 ,1-999:系統用戶,1000+:為登入用戶
if [ $# -lt 1 ]; then
echo "A argument is needed."
exit 1
fi
# 如何輸入的用戶名存在
# 注意通過命令來判斷成功與否不能加[]
if id -u $1 &>/dev/null;then
userid=$(id -u $1)
if [ $userid -eq 0 ];then
echo "Administrator"
elif [ $userid -gt 1 -a $userid -lt 499 ];then
echo " System user"
elif [ $userid -ge 500 ];then
echo "Login user"
fi
else
echo "NO such user."
fi
3.寫一個腳本
(1)列出如下菜單給用戶
disk) show disks info
mem)show memory info
cpu)show cpu info
*)quit
(2)提示用戶給出自己的選擇,而后顯示對應其選擇的相應系統信息
#!/bin/bash
cat << EOF
disk) show disks info
mem)show memory info
cpu)show cpu info
*)quit
EOF
read -p "Please input your option:" option
# 如果用戶輸入的是大寫,直接將大寫轉變為小寫
option=$(echo $option | tr [A-Z] [a-z])
if [ $option == "disk" ]; then
fdisk -l
elif [ $option == "mem" ]; then
free -m
elif [ $option == "cpu" ]; then
lscpu
elif [ $option == "*" ]; then
exit 1
else
echo "Wrong option"
fi
2.循環語句
2.1.bash的循環分類:
for循環
while循環
until循環
2.1.1.for 循環
1.兩種格式
第一種格式:遍歷列表
第二種格式:控制變量
(1)遍歷列表
for 變量 in 列表; do
循環體
done
進入條件:只要列表中有元素,即可進入循環
退出循環:列表中的元素遍歷完成
列表生成的方式
1)直接取出
例如: user1 user2 user3
2)整數列表
例如 {1..100}
例如 `seq 1 2 100` 注意:中間的2表示步長
3)返回列表的命令
`ls /var/log/`
4)glob
例如: /var/log/*
5)變量引用,如:@* ,
示例
示例1:
#!/bin/bash
for username in user1 user2 user3;do
if id $username &>/dev/null;then
echo "$username is already exists."
else
useradd $username
echo "Add &username success"
done
示例:2:求100內所有正整數之和;
#!/bin/bash
#
declare -i sum=0
for i in {1..100}; do
sum=$[ $sum+$i ]
done
echo "$sum"
示例3:列出/var/log/目錄下所有文件的類型;
#!/bin/bash
#
for option in /var/log/*; do
if [ -f $option ];then
echo "$option is Common file"
elif [ -d $option ];then
echo "$option is Directory"
elif [ -L $option ];then
echo "$option is Symbolic link"
elif [ -b $option ];then
echo "$option is block special file"
elif [ -c $option ];then
echo "$option is character special file"
elif [ -S $option ];then
echo "$option is Socket file"
else
echo "Unknow"
fi
done
練習
練習1:分別求100以內所有偶數之和,奇數之和;
#!/bin/bash
#
declare -i oven=0
declare -i odd=0
for i in {1..100}; do
count=$[ $i % 2 ]
if [[ $count == 0 ]]; then
oven=$[ $oven + $i ]
else
odd=$[ $odd + $i ]
fi
done
echo "oven is $oven"
echo "odd is $odd"
練習2:計算當前用戶的id之和;
#!/bin/bash
#
declare -i idcount=0
userRow=$(wc -l /etc/passwd|cut -d" " -f1)
# 這里不能使用{},作為列表,用seq:for i in `seq 1 $userRow`; do
for i in $(seq 1 $userRow); do
userName=$(cut -d: -f1 /etc/passwd|sed -n "$i"p)
idcount=$[ $idcount + $(id -u $userName) ]
done
echo "$idcount"
練習3:通過腳本參數傳遞一個目錄,計算所有的文本文件的行數之和,并說明文件的總數;
#/bin/bash
#
if [[ $# < 1 ]];then
echo "A argument is needed."
exit 1
fi
declare -i fileCounts=0
declare -i rowsCounts=0
# 文件數
fileCounts=$( find $1 -type f | wc -l )
for i in `seq 1 $fileCounts`; do
#這里的egrep其實可以不要,也可以取出行數
rowCount=$(find $1 -type f -exec wc -l {} \; | cut -d" " -f1 | sed -n "$i"p)
rowsCounts=$[ $rowsCounts + $rowCount ]
done
echo "fileCounts is $fileCounts , rowsCounts is $rowsCounts"
(2)控制變量
for((i=1;i<10;i++));do
進入循環代碼
done
2.1.2.while 循環
格式
while CONDITION ; do
循環體
循環控制變量的修正表達式
done
進入條件:CONDITION測試為“真”
退出條件:CONDITION測試為“假”
示例
示例1:求100以內所有正整數之和;
#!/bin/bash
#
declare -i sum=0
declare -i i=1
while [ $i -le 100 ]; do
sum=$[ $sum+$i ]
let i++
done
echo "sum is $sum"
2.1.3.until循環
格式
until CONDITION ; do
循環體
循環控制變量
done
進入條件:CONDITION測試為“假”
退出條件:CONDITION測試為“真”
示例
示例1:求100以內所有正整數之和
#!/bin/bash
#
declare -i sum=0
declare -i i=1
until [ $i -gt 100 ];do
sum=$[ $sum+$i ]
let i++
done
echo "sum to $sum"
練習
練習1:分別使用while for until實現,求100以內所有的偶數之和,100以內奇數之和;
#!/bin/bash
#
declare -i oven=0
declare -i odd=0
#for循環
for i in {1..100}; do
count=$[ $i%2 ]
if [ $count -eq 0 ]; then
oven=$[ $oven+$i ]
else
odd=$[ $odd+$i ]
fi
done
echo "odd is $odd"
echo "oven is $oven"
oven=0
odd=0
i=1
#while循環
while [ $i -le 100 ]; do
count=$[ $i%2 ]
if [ $count -eq 0 ]; then
let oven+=$i
else
let odd+=$i
fi
let i++
done
echo "odd is $odd"
echo "oven is $oven"
oven=0
odd=0
i=1
#until循環
until [ $i -gt 100 ]; do
count=$[ $i%2 ]
if [ $count -eq 0 ]; then
let oven+=$i
else
let odd+=$i
fi
let i++
done
echo "odd is $odd"
echo "oven is $oven"
練習2:創建9個用戶,user101-user109;密碼同用戶名, 如果這些用戶存在就刪除,不存在就創建;
#!/bin/bash
for i in `seq 1 10`;do
if id user10"$i" &> /dev/null;then
userdel -r user10"$i"
else
useradd user10"$i"
echo "user10$i" | passwd --stdin user10"$i" &> /dev/null
echo "create user user10$i"
fi
done
練習3:打印九九乘法表
#!/bin/bash
# 注意:這里的echo 的 -n選項表示不換行
for((i=1;i<9;i++));do
for((j=1;j<=$i;j++));do
echo -n "$j X $i = $[ $j*$i ] "
done
echo
done
練習4:打印逆序的九九乘法表
#!/bin/bash
#
declare -i k=9
while [ $k -ge 1 ]; do
for i in `seq 1 $k| sort -n -r`;do
echo -n "$i X $k = $[ $i*$k ] "
done
echo ""
let k--
done
3.循環控制語句
continue:跳出本次循環,進入下一輪循環;
break:跳出整個循環;
sleep:程序睡眠一個時間段;
死循環:條件為true,永遠為死循環
3.1.continue語句
格式
while [ 條件1 ]; do
滿足條件執行這里的代碼
if [ 條件2 ]; then
# 跳出當前循環進入下一輪循環
continue
fi
滿足條件執行這里的代碼
done
示例:
求100以內所有的偶數之和;
#/bin/bash
#
declare -i evensum=0
for i in {1..100}; do
if [ $[ $i%2 ] -eq 1 ];then
continue
fi
let evensum+=$i
done
echo "evensum is $evensum"
#/bin/bash
#
declare -i evensum=0
declare -i i=0
while [ $i -lt 100 ]; do
let i++
if [ $[ $i%2 ] -eq 1 ];then
continue
fi
let evensum+=$i
done
echo "evensum is $evensum"
3.2.break :直接跳出整個循環
格式
while [條件1]; do
執行這里的代碼
if [條件2]; then
break
fi
執行這里的代碼
done
死循環:如何創建死循環
while true;do
循環體
done
退出方式:某個測試條件滿足的時候,讓循環體執行break命令就是
示例:
計算100以內奇數之和
#/bin/bash
# description
# author
declare -i oddsum=0
declare -i i=1
while true; do
let oddsum=$oddsum+$i
let i=$i+2
if [ $i -gt 100 ];then
break
fi
done
echo "oddsum is $oddsum"
3.3.sleep命令
示例:
每隔3秒鐘到系統上獲取已經登入的用戶的信息,其中,如果sb用戶登入了系統,則給QQ發送郵件,主題為“sb user is login”,并退出;
#/bin/bash
#
while true; do
if who | grep "^logstash\>" &> /dev/null; then
break;
fi
sleep 3
done
echo "$(date +"%F %T")logstash logged on" >> /tmp/users.log
#/bin/bash
#
until who | grep "^logstash\>" &> /dev/null; do
sleep 3
done
echo "$(date +"%F %T")logstash logged on" >> /tmp/users.log
4.while和for循環的特殊用法
4.1.while循環的特殊用法(遍歷文件的行)
格式
while read VARIABLE;do
循環體
done < /PATH/TO/FILE
意思是:依次讀取/PATH/TO/FILE文件中的每一行,且將其賦值給VARIABLE變量
示例:
找出ID號為偶數的用戶,顯示其用戶名、ID、及默認的shell;
#/bin/bash
#
while read line; do
ID=$(echo $line|cut -d: -f3)
if [ $[ $ID%2 ] -eq 0 ];then
username=$(echo $line | cut -d: -f1)
shell=$(echo $line | cut -d: -f7)
echo "username is $username, ID is $ID , shell is $shell"
fi
done < /etc/passwd
4.2.for循環的特殊用法
格式
for((控制變量初始化;條件判斷表達式;控制變量修正語句));do
循環體
done
示例:
示例1:1到100的和
#/bin/bash
#
declare -i sum=0
for((i=1;i<=100;i++));do
let sum+=$i
done
echo "sum is $sum"
示例2:打印九九乘法表
#/bin/bash
#
for((i=1;i<=9;i++));do
for((j=1;j<=i;j++));do
echo -ne "${j}X${i}=$[ ${j}*${i} ]\t"
done
echo
done
5. case語句
語法格式:
case $VARAIBLE in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
分支n
;;
esac
case支持glob風格的通配符:
*:任意長度的任意字符;
?:任意單個字符;
[]:任意單個字符;
a|b:a或b;
注意:
(1)每一個分支的兩個分號一定不能少,如果沒有兩個分號,那么每一個case 的分支都會執行
(2)雖然這里的PAT可以只用模式匹配,但是只是支持glob模式的匹配,有:* ? [ ] [^ ] a|b 這幾種方式
示例:顯示一個菜單給用戶
cpu)display cpu information
mem)display memory information
disk)display disk information
quit)quit
(1)提示用戶給出自己的選擇
(2)正確的選擇給出相應的信息,否則,提示用戶,讓用戶重新選擇正確的選項,直到用戶選擇正確為止
#!/bin/bash
#
cat << EOF
cpu)display cpu information
mem)display memory information
disk)display disk information
quit)quit
=============================
EOF
read -p "Enter your option:" option
# 這里的while,通過read命令循環輸入option,使得循環可以繼續進行
while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do
echo "please input cpu , mem , disk , quit "
read -p "Enter your option:" option
done
if [ "$option" == "cpu" ];then
lscpu
elif [ "$option" == "mem" ];then
free -m
elif [ "$option" == "disk" ];then
fdisk -l /dev/sd[a-z]
elif [ "$option" == "quit" ];then
echo "quit"
exit 0
fi
將上述題目if else示例改寫為case的判斷,會使得代碼的可讀性增強
#/bin/bash
#
cat << EOF
cpu)display cpu information
mem)display memory information
disk)display disk information
quit)quit
=============================
EOF
read -p "Enter your option:" option
# 這里的while,通過read命令循環輸入option,使得循環可以繼續進行
while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do
echo "please input cpu , mem , disk , quit "
read -p "Enter your option:" option
done
case $option in
cpu)
lscpu ;;
mem)
free -m ;;
disk)
fdisk -l /dev/sd[a-z] ;;
*)
echo "quit"
exit 0 ;;
esac
示例:寫一個服務框架腳本;
$lockfile,值/var/lock/subsys/SCRIPT_NAME
(1)此腳本可接受start,stop,restart,status四個參數之一;
(2)如果參數非此四者,則提示使用幫助后退出;
(3)start,則創建lockfile,并顯示啟動;stop則刪除lockfile,并顯示停止;restart,則先刪除此文件再創建此文件,而后顯示重啟完成;status,如果lockfile存在,則顯示running,否則,則顯示為stopped.
#!/bin/bash
#
# chkconfig: - 50 50
# description: test service script
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog
case $1 in
start)
if [ -f $lockfile ]; then
echo "$prog is running yet."
else
touch $lockfile
[ $? -eq 0 ] && echo "start $prog finshed."
fi
;;
stop)
if [ -f $lockfile ]; then
rm -f $lockfile
[ $? -eq 0 ] && echo "start $prog finshed."
else
echo "$prog is running yet."
fi
;;
restart)
if [ -f $lockfile ]; then
rm -f $lockfile
touch $lockfile
echo "start $prog finshed."
else
touch -f $lockfile
echo "start $prog finshed."
fi
;;
status)
if [ -f $lockfile ]; then
echo "$prog is running yet."
else
echo "$prog is stopped."
fi
;;
*)
echo "Usage:$prog {start|stop|restart|status}"
esac
6.函數:代碼重用
模塊化編程
結構化編程
注意:定義函數的代碼段不會自動執行,在調用時執行,所謂調用函數,在代碼中給定函數名稱即可,函數名出現的任何位置,在代碼執行時候,都會自動替換為函數代碼;
6.1.語法格式:
語法一:
function f_name{
函數體
}
語法二:
f_name(){
函數體
}
函數的生命周期:每次被調用時,被創建,返回時,終止
其狀態返回結果為函數體中運行的最后一條命令的狀態結果
自定義狀態返回值,需要使用:return
return [0-255]
0: 成功
1-255:失敗
6.2.示例:
示例1:給定一個用戶名,取得用戶名的ID號,和默認的shell
#!/bin/bash
#
userinfo() {
if id "$username" &> /dev/null; then
grep "^$username\>" /etc/passwd | cut -d: -f3,7
else
echo "No such user."
fi
}
username=$1
userinfo
username=$2
userinfo
練習:
寫一個服務框架腳本名為create_file,接受start 、stop、 restart、 status 四個參數之一(這次用函數實現)
(1):如果參數非此四者,則提示使用幫助后退出
(2):如果傳遞start參數,則在/var/log目錄下創建一個與腳本名相同的文件,并顯示啟動。
(3):如果傳遞stop參數,就在/var/log目錄下刪除一個與腳本名相同的文件 ,并顯示停止。
(4):如果傳遞restart參數,就先刪除再創建此文件,而后顯示重啟完成。
(5):如果傳遞status參數, 如果文件存在,則顯示running, 否則顯示為stopped
#!/bin/bash
#
# chkconfig: - 50 50
# description: test service script
#
prog=$(basename $0)
FILE=/var/log/$prog
start() {
if [ -f $FILE ]; then
echo "$prog is running yet."
else
touch $FILE
[ $? -eq 0 ] && echo "start $prog OK."
fi
}
stop() {
if [ -f $FILE ]; then
rm -f $FILE
[ $? -eq 0 ] && echo "stop $prog finished."
else
echo "$prog is not running."
fi
}
status() {
if [ -f $FILE ]; then
echo "$prog is running"
else
echo "$prog is stopped."
fi
}
usage() {
echo "Usage: $prog {start|stop|restart|status}"
}
case $1 in
start)
start ;;
stop)
stop ;;
restart)
stop
start ;;
status)
status ;;
*)
usage
exit 1 ;;
esac
6.3.函數的返回值分為兩類
1.函數的執行結果返回值
(1):使用echo或printf命令進行輸出
(2):函數體中調用的命令的執行結果
2.函數的退出狀態碼
(1):默認取決于函數體中執行的最后一條命令的退出狀態碼
(2):自定義:return (相當于腳本中的exit)
6.4.函數可以接受參數
在調用函數的時候可以給函數傳遞參數;
在函數體中,可以使用$1, $2...引用傳遞給函數的參數,還可以使用$* 或$@調用所有的參數,$#表示傳遞的參數的個數;
在調用函數時候,在函數名后面以空白字符分割給定參數列表即可,例如:functionName arg1 arg2 arg3 arg4...
示例:
示例1:添加10個用戶,添加用戶的功能使用函數實現,用戶名作為參數傳遞給函數。這里有一個注意點,就是如果直接return $? ,在函數外面是不能拿到值的。
#!/bin/bash
#
# 5: user exists
addusers() {
if id $1 &> /dev/null; then
return 5
else
useradd $1
retval=$?
return $retval
fi
}
for i in {1..10}; do
addusers ${1}${i}
# 在這里需要注意的是:每次函數的放回結果雖然可以使用$?來引用,但是在后面多次用到的時候,一定要將其使用一個變量保存起來,這里使用一個retval=$?保存了函數執行之后的狀態碼,以后為了規范起見,所有的函數返回的狀態碼都使用一個變量將其保存起來,如: variable=$? ,這樣就不怕以后引用$?是出現錯誤。
retval=$?
if [ $retval -eq 0 ]; then
echo "Add user ${1}${i} finished."
elif [ $retval -eq 5 ]; then
echo "user ${1}${i} exists."
else
echo "Unkown Error."
fi
done
練習:
練習1:寫一個腳本:要求
(1)使用函數實現ping一個主機來測試主機的在線狀態,主機地址通過參數傳遞給函數
(2)主程序:測試192.168.7.130 - 192.168.7.139 范圍內的各個主機的在線狀態
(3)如果主機在線,那么打印黃色的Online字符串,如果主機不在線打印紅色的Offline字符串
#!/bin/bash
#
if [ $# -lt 2 ];then
echo "請輸入兩個主機地址作為IP地址的檢測范圍"
exit 1
fi
START=$1
END=$2
# 檢測IP的范圍
Ping(){
ping -c1 -w1 192.168.7.13$1 &> /dev/null && echo -e "\E[1;33m 192.168.7.13$1 Online \033[0m" || echo -e "\E[1;31m 192.168.7.13$1 Offline \033[0m"
}
for i in `seq $1 $2`; do
Ping $i
done
練習2:寫一個腳本 :要求
打印NN乘法表,使用函數實現, 例如:給腳本傳遞了一個11,那么就是打印11 X 11 的乘法表
#!/bin/bash
# 注意:這里的echo 的 -n選項表示不換行
for((i=1;i<=$1;i++));do
for((j=1;j<=$i;j++));do
echo -n "$j X $i = $[ $j*$i ] "
done
echo
done
7.變量作用域
局部變量:作用域是函數的生命周期,在函數結束時被自動銷毀。定義局部變量的方法:local 變量=值
本地變量:作用域是運行腳本的shell進程的生命周期,因此,其作用域范圍是當前的shell腳本程序文件
示例
#!/bin/bash
#
name=tom
# 記得以后為了避免函數中的變量與本地變量同名,如果同名,會使得具備變量修改本地變量的值,使得本地變量的指針直接指向函數中變量的存儲空間。為了避免同名產生的錯誤,以后在函數中定義的變量都使用局部變量,在變量名前面加上一個local關鍵字
setname() {
local name=jerry
echo "Function: $name"
}
setname
echo "Shell: $name"
8.遞歸
bash shell中和其他編程語言一樣可以使用遞歸。那什么是遞歸:程序調用自身技巧稱為遞歸( recursion)
示例:
寫一個腳本,給腳本傳遞一個數值,腳本輸出這個數值的階層。例如:5!= 120
#!/bin/bash
func() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(func $[$1-1])]
fi
}
func $1
總結
以上是生活随笔為你收集整理的shell+中sum的用法_shell高级用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 网络序_Java使用网络字节序
- 下一篇: java记事本应用程序_Java教程:使