首頁 > 軟體

Shell 指令碼基礎知識

2020-06-16 18:00:59

Unix/Linux上常見的Shell指令碼直譯器有bash、sh、csh、ksh等,習慣上把它們稱作為一種Shell。我們常說有多少中Shell,其實說的是Shell指令碼直譯器。

幾種常見的Shell

**sh**
sh是由Steve Bourne 開發,是 Bourne shell 的縮寫,sh是Unix標準預設的shell。
**bash**
bash是由Brian Fox 和 Chet Ramey共同完成。是Bourne Again Shell的縮寫。bash是linux標準預設的shell。
**ash**
ash是由Kenneth Almquist編寫,linux中占用資源最少的一個小shell,它只包含24個內部命令,因而使用起來不是很方便。
**csh**
csh是linux中比較大的核心,它由以William Joy為代表的共計47位作者編成,共有52個內部命令。該shell其實是指向/bin/tcsh這樣的一個shell,就是說csh就是tcsh。
**ksh**
ksh是由Eric Gisin編寫,是Korn Shell的縮寫,共有42條內部命令。該shell最大的優點是幾乎和商業發行版的ksh完全相容。這樣就可以在不用花錢購買商業版本的情況下嘗試商業版本的效能了。

**注意:bash是linux預設的shell,它基於Bourne Shell,吸收了csh和ksh的一些特性,bash完全相容sh,就是說,用sh寫的指令碼可以不加修改的在bash中執行**

第一個Shll指令碼

$ vi hello.sh  #新建一個shell指令碼(擴充套件名為sh的檔案,sh代表shell,擴充套件名並不影響指令碼的執行。也可以直接起名hello)

在指令碼中輸入以下程式碼:

#!/bin/bash    # "#!"是一個約定的標記,它告訴系統需要使用哪一種Shell。
echo "Hello World!"

執行Shell的方法:

$ chmod +x hello.sh         #給檔案增加執行許可權
$ ./hello.sh                #執行指令碼

$ /bin/sh hello.sh        #以sh執行指令碼
$ /bin/bash hello.sh      #以bash執行指令碼

範例:
編寫一個指令碼,從標準輸入(stdin)中讀取名字,顯示在標準輸出(stdout)上。

#/bin/bash

echo "What's your name?"
read NAME
echo "Hello ${NAME}"

Shell 變數

定義變數
變數名與等號直接不能有空格。變數明的命名規則需遵循如下規則:
1、首個字元必須為字母(a-z,A-Z)
2、中間不能有空格,可以使用下劃線(_)
3、不能使用標點符號
4、不能使用shell裡的關鍵字(在命令列中使用help命令可以檢視保留關鍵字)

變數定義範例:

variableName="value"

使用變數
使用一個定義過的變數,只要在變數名前面加 $ 符號就可以了。如:

variableName="value"
echo $variableName

有些時候需要在變數名外面加上花括號幫助直譯器識別變數的邊界,如下面這種情況

SKILL=Ada
echo "I'm a good at ${SKILL}Script"

重新定義變數
已經定義的變數,可以被重新定義,如:

#!/bin/bash
NAME=Dave
echo "Hello ${NAME}"

NAME=Abby
echo "Hello ${NAME}"

唯讀變數
使用readonly命令可以將變數定義為唯讀變數,唯讀變數的值不能改變

#!/bin/bash
NAME=Dave
readonly NAME
NAME=Abby

執行指令碼會報錯,結果如下

./test.sh: line 5: NAME: readonly variable

刪除變數
使用unset命令刪除變數,變數被刪除後不能再次使用;unset命令不能刪除唯讀變數
範例:

#!/bin/bash
NAME=Dave
unset NAME
echo $NAME

執行結果不會有任何輸出。

Shell程式設計淺析 http://www.linuxidc.com/Linux/2014-08/105379.htm 

Linux Shell引數替換 http://www.linuxidc.com/Linux/2013-06/85356.htm

Shell for引數 http://www.linuxidc.com/Linux/2013-07/87335.htm

Linux/Unix Shell 引數傳遞到SQL指令碼 http://www.linuxidc.com/Linux/2013-03/80568.htm

Shell指令碼中引數傳遞方法介紹 http://www.linuxidc.com/Linux/2012-08/69155.htm

Shell指令碼傳遞命令列引數 http://www.linuxidc.com/Linux/2012-01/52192.htm

Linux Shell 萬用字元、跳脫字元、元字元、特殊字元 http://www.linuxidc.com/Linux/2014-10/108111.htm 

Linux Shell指令碼面試25問  http://www.linuxidc.com/Linux/2015-04/116474.htm

Shell特殊變數


範例

#!/bin/bash

echo "File Name : $0"
echo "First Parameter : $1"
echo "Second Parameter : $2"
echo "All Parameter : $@"
echo "All Parameter : $*"
echo "Total Number of Parameter $#"
echo "The Shell of the process ID is : $$"

執行結果:

$ ./test.sh Dave Abby
File Name : ./test.sh
First Parameter : Dave
Second Parameter : Abby
All Parameter : Dave Abby
All Parameter : Dave Abby
Total Number of Parameter 2
The Shell of the process ID is : 2752
$ echo $?     #檢視./test.sh 退出狀態。一般情況下成功返回0,失敗返回-1
0

* $* 和 $@的區別 *
很多關於shell的書本上寫當它們被雙引號包含時,$* 會將所有引數作為一個整體,而$@ 會將各個引數分開。但是,我在執行指令碼的時候並沒有發現這樣的情況。我是在Ubuntu1204版本中測試的。程式碼如下

#!/bin/bash


echo '$*='"$*"
echo '$@='"$@"

Shell替換

命令替換
命令替換是指shell可以先執行命令,將輸出結果暫時儲存,在適當的地方輸出
範例:

#!/bin/bash

DATE=`date`
echo "$DATE"

變數替換

範例:

#!/bin/bash

echo ${var:-"Hello"}
echo $var

echo ${var:="Hello"}
echo $var

echo ${var:+"World"}
echo $var

unset var
echo ${var:?"message"}
echo $var

結果如下:

$ ./test.sh 
Hello

Hello
Hello
World
Hello
./test.sh: line 13: var: message

Shell的if語句

if語句通過關係運算子判斷表示式的真假來決定執行那個分支,Shell有三種if語句。

  • if … fi 語句
  • if … else … fi 語句
  • if … elif … else … fi 語句

if … fi 語句的語法

if [ expression ]
then
    Statement(s) to be executed if expression is true
fi

**注意:**expression 和方括號之間必須有空格。否則會有語法錯誤
範例:

#!/bin/bash

a=10
b=20

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

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

if … else … fi語句語法

if [ expression ]
then
    Statement(s) to be executed if expression is true
else
    Statement(s) to be executed if expression is not true
fi

範例:

#!/bin/bash

a=10
b=20

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

if … elif …fi語句語法

if [ expression 1 ]
then
    Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
    Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
    Statement(s) to be executed if expression  3 is true
else
    Statements to be executed if expression not is true
fi  

範例:

#!/bin/bash

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 "None of the condition met"
fi

Shell運算子

bash支援很多運算子。包括算數運算子、關係運算子、布林運算子、字串運算子和檔案測試運算子。
算數運算子

bash中實現數學運算的語法。
- 使用expr表示式計算工具。 expr 1 + 2
- [1+2]
關係運算子只支援數位,不支援字串。除非字串的值是數位。
範例:

#!/bin/bash

a=10
b=20

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

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

if [ $a -gt $b ]
then
        echo "a > b"
else
        echo "a < b"
fi

if [ $a -lt $b ]
then
        echo "a < b"
else
        echo "a > b"
fi

if [ $a -ge $b ];then echo "a > b";else echo "a < b";fi
if [ $a -le $b ];then echo "a < b";else echo "a > b";fi

布林運算子

範例:

#!/bin/bash

a=10
b=20

if [ ! $a -eq $b ]; then echo "a == b"; else echo "a != b"; fi

if [ $a -lt $b -o $b -gt $a ]; then echo "a < b"; else echo "a > b"; fi

if [ $a -le $b -a $b -ge $a ]; then echo "a < b"; else echo "a > b"; fi

字串運算子

範例:

#!/bin/bash

a="abc"
b="edf"

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

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

if [ -z $a -o -z $b ]; then echo "string length isn't zero";
        else echo "string length is zero"; fi

if [ -n $a -a -n $b ]; then echo "string length is zero"
        else echo "string length isn't zero"; fi

if [ $a -a $b ];then echo "string length is zero"
        else echo "string length isn't zero"; fi

檔案測試運算子
檔案測試運算子用於檢測檔案的各種屬性
範例:

#!/bin/bash



if [ -b $1 ]; then echo "$1 is block file"; else echo "$1 is not block file"; fi

if [ -c $1 ]; then echo "$1 is str file"; else echo "$1 is not str file"; fi

if [ -d $1 ]; then echo "$1 is directory file"; else echo "$1 is not directory file"; fi

if [ -f $1 ]; then echo "$1 is ordinary file"; else echo "$1 is not ordinary file"; fi

if [ -g $1 ]; then echo "$1 SGID bit"; else echo "$1 not SGID bit"; fi

if [ -k $1 ]; then echo "$1 Sticky bit"; else echo "$1 not Sticky not bit"; fi

if [ -p $1 ]; then echo "$1 is pipe file"; else echo "$1 is not pipe file"; fi

if [ -u $1 ]; then echo "$1 SUID bit"; else echo "$1 not SUID bit"; fi

if [ -r $1 ]; then echo "$1 is read file"; else echo "$1 is not read file"; fi

if [ -w $1 ]; then echo "$1 is write file"; else echo "$1 is not write file"; fi

if [ -x $1 ]; then echo "$1 is execute file"; else echo "$1 is not execute file"; fi

if [ -s $1 ]; then echo "$1 is not zero"; else echo "$1 is  zero"; fi

if [ -e $1 ]; then echo "$1 exists"; else echo "$1 not exists"; fi

執行結果:

$ ./test.sh  test.sh
test.sh is not block file
test.sh is not str file
test.sh is not directory file
test.sh is ordinary file
test.sh not SGID bit
test.sh not Sticky not bit
test.sh is not pipe file
test.sh not SUID bit
test.sh is read file
test.sh is write file
test.sh is execute file
test.sh is not zero
test.sh exists
[關於SUID,SGID,Sticky的屬性請參考:](http://www.linuxidc.com/Linux/2015-05/116982.htm) 

 

更多詳情見請繼續閱讀下一頁的精彩內容http://www.linuxidc.com/Linux/2015-05/116981p2.htm 


IT145.com E-mail:sddin#qq.com