我本身對shell腳本的理解就是一系列的shell命令加入邏輯關係,實現相似「批處理」的功能。而不是簡單的命令的堆砌,那樣的shell腳本bug重重.python
腳本開頭需加#!/bin/bash (python 用#!/usr/bin/env python) 做爲解釋器,若不指定解釋器,則須要對應的解釋器來執行腳本web
[root@server24 shell]# bash test.sh
[root@server24 shell]# python test.py
當shell腳本以非交互的方式運行時,他先會查找環境變量ENV,該變量指定了一個環境文件(一般是 .bashrc),而後從該環境變量文件開始執行,當讀了ENV文件後,SHELL開始執行shell腳本中的內容。shell
格式:rename old_name new_name file編程
[root@server24 shell]# ll
total 8
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_10.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_1.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_2.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_3.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_4.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_5.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_6.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_7.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_8.jpg
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_9.jpg
[root@server24 shell]# for i in `ls *.jpg`; do rename ".jpg" ".png" $i; done
[root@server24 shell]# ll
total 8
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_10.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_1.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_2.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_3.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_4.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_5.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_6.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_7.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_8.png
-rw-r--r-- 1 root root 0 Jun 6 13:20 echo_33804139_9.png
${}雖然只有三個字符,可是功能特別強大。下面簡單示例其功能
假設定義兩個變量test,result
result=${test:-UNSET} 其表示的意思是:當test沒有賦值時,將UNSET賦值給result,防止變量由於無定義,而致使最終結果無值。但並不給test賦值ruby
[root@server24 shell]# result=${test:-'None'}
[root@server24 shell]# echo $result
None
[root@server24 shell]# echo $test
[root@server24 shell]#
result=${test:=UNSET} 其表示的意思是: 當test沒有賦值時,將UNSET賦值給test。防止變量無定義bash
[root@server24 shell]# result=${test:='None'}
[root@server24 shell]# echo $result
None
[root@server24 shell]# echo $test
None
[root@server24 shell]#
常見的計算變量長度的方法有app
echo ${#test}
echo $test | wc -w
echo $(expr length 「$test」)
對如上三種方法進行性能測試(將計算變量時間擴大10000倍)svg
time for i in `seq 10000`;do count=${#chars} ; done
real 0m1.049s
user 0m1.047s
sys 0m0.000s
time for i in `seq 10000`;do count=`echo "$chars" | wc -m` ; done
real 0m32.815s
user 0m6.768s
sys 0m23.580s
time for i in `seq 10000`;do count=`echo expr length "$chars"` ; done
real 0m12.342s
user 0m1.212s
sys 0m6.831s
從上面結果顯示,雖然三種計算方法擁有一樣的執行功能,但在性能(速度)上千差萬別,因此通常在shell編程中勁量使用內置操做或函數完成,而不是使用外部調用命令。函數
(()) let expr bc $[]
(()) 通常置於$((….))語法中,如同引用雙引號功能性能
let 效率無(())高
[root@server22 ~]# i=2
[root@server22 ~]# let i=i+3
[root@server22 ~]# echo $i
5
expr 將其後的串解釋爲表達式並計算其值,運算符先後必需有空格,特殊字符須要用轉義字符
[root@server22 ~]# expr 2+2
2+2
[root@server22 ~]# expr 2 * 2
expr: syntax error
[root@server22 ~]# expr 2 \* 2
4
使用 expr $[$a*$b] 則不須要空格
[root@server22 ~]# expr $[2*3]
6
拓展:expr的其餘用法
使用expr可判斷其拓展名,若爲真,返回非0: expr 「$1」 : 「.*.pub」
[root@server22 ~]# expr "test.pub" : ".*.pub"
8
[root@server22 ~]# expr "test.txt" : ".*.pub"
0
使用expr也可判斷是否爲整型
[root@server22 ~]# expr g + 0
expr: non-numeric argument
bc 支持小數的運算
[root@server22 ~]# echo 5.43+4 |bc #中間空格無關緊要
9.43
[root@server22 ~]# echo `seq -s "+" 10`| bc
55 #1..10累加
[root@server22 ~]# echo "obase=2;256"| bc
100000000 ##進制轉換
[root@server22 ~]# echo "scale=2; 5.23 / 3.4 " | bc
1.53 #保留兩位小數
附加一個在練習腳本時遇到的一個小問題
簡單數值計算
#!/bin/bash
function error() {
echo 'input error'
exit 1
}
[ $# -eq 3 ] || error
expr $1 + 0 > /dev/null 2>&1
[ $? -ne 0 ] && error
#echo $2
[ "${2}" != '+' ] && [ $2 != '-' ] && [ "${2}" != '*' ] && [$2 != '/' ] && [ ${2} != '**' ] && [ "$2" != '%' ] && error
expr $3 + 0 > /dev/null 2>&1
[ $? -ne 0 ] && error
echo $(($1 $2 $3))
[root@server24 shell]# ./guo_test_1.sh 5 \* 8
./guo_test_1.sh: line 11: [: too many arguments
40
在執行腳本時,運算符遇到*、**等特殊字符時就會報錯,在傳參時明明作了字符轉義,字符串比較時又使用了其特殊用法,最後計算時又恢復了其字面意思。搞不懂了
====================修改於2016年7月24日=======================
將以前腳本從新執行了一下,觀察獲得:運算符在第一次的判斷語句中是按照字面意思去執行,可是在第二次判斷中,使用了其特殊用法,致使整個判斷語句終止。在後面的執行過程當中與判斷無關,因此計算時還會按照咱們設定的去運算。爲何第二次會變成那樣呢?原來在腳本里面第一次判斷時,我加了雙引號表示傳入的參數爲一個字符串,而第二次沒有加,因此將全部變量值打印出來,所以將腳本修改以下:
#!/bin/bash
function error() {
echo 'input error'
exit 1
}
[ $# -eq 3 ] || error
expr $1 + 0 > /dev/null 2>&1
[ $? -ne 0 ] && error
[ "$2" != '+' ] &&
[ "$2" != '-' ] &&
[ "$2" != '*' ] &&
[ "$2" != '/' ] &&
[ "$2" != '**' ]
&& [ "$2" != '%' ] && error
expr $3 + 0 > /dev/null 2>&1
[ $? -ne 0 ] && error
echo $(($1 $2 $3))
在嘗試過程當中曾用case語句去執行,可是這種方法有點繁瑣。
#!/bin/bash
function error() {
echo "input error"
exit 1
}
[ $# -eq 3 ] || error
expr $1 + 0 > /dev/null 2>&1
[ $? -ne 0 ] && error
expr $3 + 0 > /dev/null 2>&1
[ $? -ne 0 ] && error
case $2 in
'*')
echo $(($1 $2 $3))
;;
'**')
echo $(($1 $2 $3))
;;
'+')
echo $(($1 $2 $3))
;;
'-')
echo $(($1 $2 $3))
;;
'/')
echo $(($1 $2 $3))
;;
'%')
echo $(($1 $2 $3))
;;
*)
error
;;
esac
[root@server22 shell]# ./compu_1.sh 3 \** 4
81
[root@server22 shell]# ./compu_1.sh 3 \* 4
12
[root@server22 shell]# ./compu_1.sh 3 / 4
0
[root@server22 shell]# ./compu_1.sh 3 % 4
3
[root@server22 shell]# ./compu_1.sh 3 + 4
7
[root@server22 shell]# ./compu_1.sh 3 - 4
-1