高階bash/shell指令碼程式設計指南

造夢先森發表於2017-10-21

簡介

Bash(GNU Bourne-Again Shell)是一個為GNU計劃編寫的Unix shell,它是許多Linux平臺預設使用的shell。

shell是一個命令直譯器,是介於作業系統核心與使用者之間的一個絕緣層。準確地說,它也是能力很強的計算機語言,被稱為解釋性語言或指令碼語言。它可以通過將系統呼叫、公共程式、工具和編譯過的二進位制程式”粘合“在一起來建立應用,這是大多數指令碼語言的共同特徵,所以有時候指令碼語言又叫做“膠水語言”

事實上,所有的UNIX命令和工具再加上公共程式,對於shell指令碼來說,都是可呼叫的。Shell指令碼對於管理系統任務和其它的重複工作的例程來說,表現的非常好,根本不需要那些華而不實的成熟緊湊的編譯型程式語言。

執行Bash指令碼的方式:

# 使用shell來執行
$ sh hello.sh

# 使用bash來執行
$ bash hello.sh

# 使用.來執行
$ . hello.sh

#使用source來執行
$ source hello.sh

初步練習:

#!/bin/bash

# 使用重定向
echo "Hello World" > test.txt

# 使用指令碼清除/var/log下的log檔案
LOG_DIR=/var/log

cd $LOG_DIR
> test.log 
或
echo "" > test.log 
或
cat /dev/null > test.log 

# 複製test.txt的內容到test.log
cp test.{txt,log}

許可權不夠怎麼辦,我們可以使用

sudo sh -c "cat /dev/null > /var/log/wtmp "

讓整個命令都具有sudo的許可權執行

bash特殊字元

1,終止case選項(雙分號)

#!/bin/bash

VARNAME=b

case "$VARNAME" in
     [a-z]) echo "abc";;
     [0-9]) echo "123";;
esac

2,引號

同樣是$VARNAME,單引號會直接認為是字元,而雙引號認為是一個變數

#!/bin/bash
VARNAME=b

echo '$VARNAME' # 輸出 $VARNAME
echo "$VARNAME" # 輸出 b

3,冒號

#!/bin/bash

while :   #相當於 while true
do
    echo "endless loop"
done
#!/bin/bash

condition=5

if [ $condition -gt 0 ] #gt表示greater than,也就是大於,同樣有-lt(小於),-eq(等於) 
then :   # 什麼都不做,退出分支
else
    echo "$condition"
fi

4,陣列元素

#!/bin/bash

arr=(12 22 32)
arr[0]=10
echo ${arr[0]}

5,管道(|)

分析前邊命令的輸出,並將輸出作為後邊命令的輸入。這是一種產生命令鏈的好方法。

輸入如下程式碼,作用是將小寫字母轉化為大寫

#!/bin/bash

tr 'a-z' 'A-Z'
exit 0

現在讓我們輸送ls -l的輸出到指令碼中:

$ chmod 755 test.sh
$ ls -l | ./test.sh

輸出的內容均變為了大寫字母。

6,破折號(-):重定向stdin或stdout

下面指令碼用於備份最後24小時當前目錄下所有修改的檔案.

#!/bin/bash

# 如果在命令列中沒有指定備份檔案的檔名,那麼將預設使用"backup-MM-DD-YYYY.tar"
BACKUPFILE=${1:-backup}-$(date +%m-%d-%Y).tar

tar cvf - `find . -mtime -1 -type f -print` > $BACKUPFILE
gzip $BACKUPFILE
echo "Directory $PWD backed up in \"$BACKUPFILE.gz\"."

exit 0

引數

從命令列傳遞到指令碼的引數:$0,$1,$2,$3

$0就是指令碼檔案自身的名字,$1 是第一個引數,$2 是第二個引數,$3 是第三個引數,然後是第四個。$9 之後的位置引數就必須用大括號括起來了,比如,${10},${11},${12}

其他引數:

$# : 傳遞到指令碼的引數個數
$* : 以一個單字串顯示所有向指令碼傳遞的引數。與位置變數不同,此選項引數可超過 9$$ : 指令碼執行的當前程式 ID$! : 後臺執行的最後一個程式的程式 ID$@ : 與$#相同,但是使用時加引號,並在引號中返回每個引數
$: 顯示shell使用的當前選項,與 set命令功能相同
$? : 顯示最後命令的退出狀態。 0表示沒有錯誤,其他任何值表明有錯誤。

檔案

#!/bin/bash

file="/home/shiyanlou/test.sh"

if [ -r $file ]
then
   echo "The file is readable"
else
   echo "The file is not readable"
fi

if [ -e $file ]
then
   echo "File exists"
else
   echo "File not exists"
fi

引數說明:

-e filename 如果 filename存在,則為真
-d filename 如果 filename為目錄,則為真 
-f filename 如果 filename為常規檔案,則為真
-L filename 如果 filename為符號連結,則為真
-r filename 如果 filename可讀,則為真 
-w filename 如果 filename可寫,則為真 
-x filename 如果 filename可執行,則為真
-s filename 如果檔案長度不為0,則為真
-h filename 如果檔案是軟連結,則為真
filename1 -nt filename2 如果 filename1比 filename2新,則為真。
filename1 -ot filename2 如果 filename1比 filename2舊,則為真。

流程控制

1,if else 語法格式:

a=10
b=20
if [ $a == $b ]
then
   echo "a == b"
elif [ $a -gt $b ]
then
   echo "a > b"
elif [ $a -lt $b ]
then
   echo "a < b"
else
   echo "Ineligible"
fi

2,for迴圈一般格式:

for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

3,while語句

int=1

while (( $int<=5 ))
do
    echo $int
    let "int++" #使用Bash let命令,不需要加上$來表示變數

done

while迴圈可用於讀取鍵盤資訊。下面的例子中,輸入資訊被設定為變數MAN,按結束迴圈。

echo 'press <CTRL-D> exit'
echo -n 'Who do you think is the most handsome: '
while read MAN
do
    echo "Yes!$MAN is really handsome"
done

無限迴圈。要跳出這個迴圈,返回到shell提示符下,需要使用break命令。

#!/bin/bash
while :
do
    echo -n "Enter a number between 1 and 5:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "The number you entered is $aNum!"
        ;;
        *) echo "The number you entered is not between 1 and 5! game over!"
            break
        ;;
    esac
done

算數運算

  • 原生bash不支援簡單的數學運算,但是可以通過其他命令來實現,例如 awk 和 expr,expr 最常用。
  • expr 是一款表示式計算工具,使用它能完成表示式的求值操作
  • 注意使用的反引號(esc鍵下邊)
  • 表示式和運算子之間要有空格$a + $b寫成$a+$b不行
  • 條件表示式要放在方括號之間,並且要有空格[ $a == $b ]寫成[$a==$b]不行 乘號(*)前邊必須加反斜槓()才能實現乘法運算
#!/bin/bash

a=10
b=20

val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $b / $a`
echo "b / a : $val"

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then
   echo "a == b"
fi
if [ $a != $b ]
then
   echo "a != b"
fi

相關文章