bash腳本
1、終端打印
1、單雙引號(echo)
雙引號:
①在雙引號里面打不出!
②雙引號,可以在文本中使用“;”,“;”在bash中被用作命令定界符。
單引號:
變量替換在單引號中無效。
2、printf:不會自動添加換行符,要手動添加
如下:
結果:
3、補充:
echo 要使用轉義系列需要加e,!號除外
2、變量和環境變量
腳本語言通常不需要在使用變量之前聲明變量類型,直接賦值就可以了。
Bash中,每一個變量的值都是字符串,無論變量賦值時有沒有用引號,值都會以字符串形式存儲。
1、查看某個進程的環境變量
env查看所有的環境變量 cat /proc/$PID/environ
有很多,截取一點,其中的環境變量用null字符"\0"連接,要想每行顯示一個,可以將"\0"轉化為"\n"。如下
2、變量賦值與引用
var=value(等號兩邊沒有空格 var = value是錯誤的) 如果,value中不包含任何空白字符,就不需要用引號 變量名前加$就表示引用,可以在雙引號中引用變量
環境變量是由父進程繼承過來的,要用export來設置,設置后從當前shell腳本任務執行的應用程序都會繼承這個變量。
比如PATH這個環境變量,就是查找文件時候的搜索路徑,要在PATH中添加一條新的路徑
PATH="PATH:/home/user/bin" export PATH
使用單引號時變量不會被引用。
檢測是否為超級用戶:
數值比較 -eq:是否等于; [ $num1 -eq $num2 ] -ne:是否不等于; -gt:是否大于; -ge:是否大于等于; -lt:是否小于; -le:是否小于等于; 字符串測試: ==:是否等于; >:是否大于; <:是否小于; !=:是否不等于; =~:左側字符串是否能夠被右側的PATTERN所匹配; -z "STRING":判斷指定的字串是否為空;空則為真,不空則假; -n "STRING":判斷指定的字符串是否不空;不空則真,空則為假;
3、使用shell進行數學運算
算數操作用let、(())和[],bc是專門做運算的命令
使用let運算的后面的變量引用不用加$
計算1加到100的和:
自加let no1++ 或 let no+=6 自減let no1-- 或 let no-=6
[]的使用方法類let,(())也是。
bc是個高級的工具,可以計算浮點數和高級函數,以上都不支持浮點計算。
4、條件判斷式
if [ ]; then command; fi 或: if [ ];then command1; else command2; fi 或: if [ ] ;then command; elif [ ];then command2; else command3; fi
通過參數傳遞一個用戶名給腳本,此用戶不存時,則添加之;且用戶名為密碼:
另外一種方法
練習2:通過命令行參數給定一個用戶名,判斷其ID號是偶數還是奇數;
練習3:通過命令行參數給定兩個文本文件名,如果某文件不存在,則結束腳本執行;都存在時返回每個文件的行數,并說明其中行數較多的文件;
示例:腳本參數傳遞一個文件路徑給腳本,判斷此文件的類型;
#!/bin/bash # if [ $# -lt 1 ]; then echo "At least on path." exit 1 fi if ! [ -e $1 ]; then echo "No such file." 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 "Unkown." fi 注意:if語句可嵌套; 練習:寫一個腳本 (1) 傳遞一個參數給腳本,此參數為用戶名; (2) 根據其ID號來判斷用戶類型: 0: 管理員 1-999:系統用戶 1000+:登錄用戶 #!/bin/bash # [ $# -lt 1 ] && echo "At least on user name." && exit 1 ! id $1 &> /dev/null && echo "No such user." && exit 2 userid=$(id -u $1) if [ $userid -eq 0 ]; then echo "root" elif [ $userid -ge 1000 ]; then echo "login user." else echo "System user." fi 練習:寫一個腳本 (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 "Your choice: " option if [[ "$option" == "disk" ]]; then fdisk -l /dev/[sh]d[a-z] elif [[ "$option" == "mem" ]]; then free -m elif [[ "$option" == "cpu" ]];then lscpu else echo "Unkown option." exit 3 fi
5、循環執行
bash腳本: for循環 while循環 until循環 for循環: 兩種格式: (1) 遍歷列表 (2) 控制變量 遍歷列表: for VARAIBLE in LIST; do 循環體 done 進入條件:只要列表有元素,即可進入循環; 退出條件:列表中的元素遍歷完成; LISTT的生成方式: (1) 直接給出; (2) 整數列表 (a) {start..end} 如:{1..10} (b) seq [start [incremtal]] last 如: seq 6 16 生成從6到16的數字列表,可以指定步長。 seq 1 2 6 (3) 返回列表的命令 (4) glob (5) 變量引用 $@, $* ... 示例:求100以內所有正整數之和; #!/bin/bash # declare -i sum=0 for i in {1..100}; do echo "\$sum is $sum, \$i is $i" sum=$[$sum+$i] done echo $sum 示例:判斷/var/log目錄下的每一個文件的內容類型 #!/bin/bash # for filename in /var/log/*; do if [ -f $filename ]; then echo "Common file." elif [ -d $filename ]; then echo "Directory." elif [ -L $filename ]; then echo "Symbolic link." elif [ -b $filename ]; then echo "block special file." elif [ -c $filename ]; then echo "character special file." elif [ -S $filename ]; then echo "Socket file." else echo "Unkown." fi done
練習: 1、分別求100以內所有偶數之和,以及所有奇數之和;
2、計算當前系統上的所有用的id之和;
示例:求100以內所有正整數之和; #!/bin/bash # declare -i sum=0 declare -i i=1 until [ $i -gt 100 ]; do let sum+=$i let i++ done echo $sum #!/bin/bash # declare -i sum=0 declare -i i=1 while [ $i -le 100 ]; do let sum+=$i let i++ done echo $sum while: while CONDITION; do 循環體 循環控制變量修正表達式 done 打印九九乘法表;
循環控制:
break:停止指定層循環 continue:跳過循環體中的剩余命令。
case
示例1:顯示一個菜單給用戶; cpu) display cpu information mem) display memory information disk) display disks information quit) quit 要求:(1) 提示用戶給出自己的選擇; (2) 正確的選擇則給出相應的信息;否則,則提示重新選擇正確的選項; #!/bin/bash # cat << EOF cpu) display cpu information mem) display memory infomation disk) display disks information quit) quit =============================== EOF read -p "Enter your option: " option while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do echo "cpu, mem, disk, quit" read -p "Enter your option again: " option done if [ "$option" == "cpu" ]; then lscpu elif [ "$option" == "mem" ]; then free -m elif [ "$option" == "disk" ]; then fdisk -l /dev/[hs]d[a-z] else echo "quit" exit 0 fi case語句的語法格式: case $VARAIBLE in PAT1) 分支1 ;; PAT2) 分支2 ;; ... *) 分支n ;; esac case支持glob風格的通配符: *:任意長度的任意字符; ?:任意單個字符; []:范圍內任意單個字符; a|b:a或b; 示例:寫一個服務框架腳本; $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 "stop $prog finished." else echo "$prog is not running." fi ;; restart) if [ -f $lockfile ]; then rm -f $lockfile touch $lockfile echo "restart $prog finished." else touch -f $lockfile echo "start $prog finished." fi ;; status) if [ -f $lockfile ]; then echo "$prog is running" else echo "$prog is stopped." fi ;; *) echo "Usage: $prog {start|stop|restart|status}" exit 1 esac
6、函數
過程式編程:代碼重用 模塊化編程 結構化編程 把一段獨立功能的代碼當作一個整體,并為之一個名字;命名的代碼段,此即為函數; 注意:定義函數的代碼段不會自動執行,在調用時執行;所謂調用函數,在代碼中給定函數名即可; 函數名出現的任何位置,在代碼執行時,都會被自動替換為函數代碼; 語法一: function f_name { ...函數體... } 語法二: f_name() { ...函數體... }
函數的生命周期:每次被調用時,創建函數,返回時終止,即函數代碼引用完了,bash腳本每次都有一個狀態返回值,函數也有返回值。在函數中使用echo打印的返回值,也有狀態返回值。其狀態返回結果為函數體中運行的最后一條命令的狀態結果;
自定義狀態返回值,需要使用:return(終止),相當于exit。 return [0-255] 0: 成功 1-255: 失敗 示例:給定一個用戶名,取得用戶的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 示例2:服務腳本框架 #!/bin/bash # # chkconfig: - 50 50 # description: test service script # prog=$(basename $0) lockfile=/var/lock/subsys/$prog 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 "stop $prog finished." else echo "$prog is not running." fi } status() { if [ -f $lockfile ]; 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 函數返回值: 函數的執行結果返回值: (1) 使用echo或printf命令進行輸出; (2) 函數體中調用的命令的執行結果; 函數的退出狀態碼: (1) 默認取決于函數體中執行的最后一條命令的退出狀態碼; (2) 自定義:return
函數可以接受參數: 傳遞參數給函數: 在函數體中當中,可以使用$1,$2, ...引用傳遞給函數的參數;還可以函數中使用$*或$@引用所有參數,$#引用傳遞的參數的個數; 在調用函數時,在函數名后面以空白符分隔給定參數列表即可,例如,testfunc arg1 arg2 arg3 ... 示例:添加10個用戶, 添加用戶的功能使用函數實現,用戶名做為參數傳遞給函數; #!/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=$? 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 練習:寫一個腳本; 使用函數實現ping一個主機來測試主機的在線狀態;主機地址通過參數傳遞給函數; 主程序:測試172.16.1.1-172.16.67.1范圍內各主機的在線狀態; 練習:寫一個腳本; 打印NN乘法表; 變量作用域: 局部變量:作用域是函數的生命周期;在函數結束時被自動銷毀; 定義局部變量的方法:local VARIABLE=VALUE 本地變量:作用域是運行腳本的shell進程的生命周期;因此,其作用范圍為當前shell腳本程序文件; 示例程序: #!/bin/bash # name=tom setname() { local name=jerry echo "Function: $name" } setname echo "Shell: $name"
函數遞歸: 函數直接或間接調用自身; 10!=10*9!=10*9*8!=10*9*8*7!=... n n*(n-1)!=n*(n-1)*(n-2)!= #!/bin/bash # fact() { if [ $1 -eq 0 -o $1 -eq 1 ]; then echo 1 else echo $[$1*$(fact $[$1-1])] fi } fact $1 1,1,2,3,5,8,13,21,... #!/bin/bash # fab() { if [ $1 -eq 1 ]; then echo -n "1 " elif [ $1 -eq 2 ]; then echo -n "1 " else echo -n "$[$(fab $[$1-1])+$(fab $[$1-2])] " fi } for i in $(seq 1 $1); do fab $i done echo
原創文章,作者:N24_yezi,如若轉載,請注明出處:http://www.www58058.com/61364
bash 相關的知識總結的很好,如能附加一些特殊變量的說明就更全面了