shell基礎筆記

什麼是shell腳本

我自己對shell腳本的理解就是一系列的shell命令加入邏輯關係,實現類似“批處理”的功能。而不是簡單的命令的堆砌,那樣的shell腳本bug重重.

腳本開頭需加#!/bin/bash (python 用#!/usr/bin/env python) 作爲解釋器,若不指定解釋器,則需要對應的解釋器來執行腳本

[root@server24 shell]# bash test.sh
[root@server24 shell]# python test.py

bash腳本的執行

當shell腳本以非交互的方式運行時,他先會查找環境變量ENV,該變量指定了一個環境文件(通常是 .bashrc),然後從該環境變量文件開始執行,當讀了ENV文件後,SHELL開始執行shell腳本中的內容。

rename 更名

格式: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賦值

[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。防止變量無定義

[root@server24 shell]# result=${test:='None'}
[root@server24 shell]# echo $result
None
[root@server24 shell]# echo $test
None
[root@server24 shell]# 

計算變量長度方法及性能比較

常見的計算變量長度的方法有

echo ${#test}
echo $test | wc -w
echo $(expr length “$test”)

對如上三種方法進行性能測試(將計算變量時間擴大10000倍)

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

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