1. 程式人生 > >Shell程式設計 筆記

Shell程式設計 筆記

shell程式設計就是將shell命令寫在一個.sh檔案裡面,類似批處理檔案,一次執行多條語句

使用readonly關鍵字可以建立只讀變數,不能修改

readonly mm="ss"
#這條語句報錯
mm='ss'

unset 可以刪除已經宣告的變數

mm ='mm'
unset mm
#這條語句沒有輸出
echo $mm

shell迴圈,以下程式碼實現迴圈

for skill in  Ada Coffe Action Java
do
    echo "I am good at ${skill}Script"
done
#輸出
I am good at AdaScript
I am good at
CoffeScript I am good at ActionScript I am good at JavaScript

有一些變數是特殊變數,代表特殊的含義

變數名 含義
$0 當前指令碼的檔名
$n 傳遞給指令碼或函式的引數。n 是一個數字,表示第幾個引數。例如,第一個引數是$1,第二個引數是$2。
$# 傳遞給指令碼或函式的引數個數。
$* 傳遞給指令碼或函式的所有引數。
$@ 傳遞給指令碼或函式的所有引數。被雙引號(” “)包含時,與$* 稍有不同,下面將會講到。
$? 上個命令的退出狀態,或函式的返回值。
$$ 當前Shell程序ID。對於 Shell 指令碼,就是這些指令碼所在的程序ID。

shell指令碼引數,下例實現傳遞引數並輸出

echo $1
echo $2
#執行 ./test.sh run log
#輸出 
run
log

$* 和$@的區別

都是表示輸入引數的集合,$* 和 $@沒有區別,”$

*”和”$@”(被雙引號包裹起來的)有區別,區別在於,$* 被引號包圍時會將連續的若干個引號包圍的引數當做一個引數,例如:

#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\[email protected]=" [email protected]
echo "\"\[email protected]\"=" "[email protected]"
echo "print each param from \$*"
for var in $*
do
    echo "$var"
done
echo "print each param from \[email protected]"
for var in [email protected]
do
    echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
    echo "$var"
done
echo "print each param from \"\[email protected]\""
for var in "[email protected]"
do
    echo "$var"
done
#執行./test.sh "a" "b" "c" "d",
#輸出
$*=  a b c d
"$*"= a b c d
[email protected]=  a b c d
"[email protected]"= a b c d
print each param from $*
a
b
c
d
print each param from [email protected]
a
b
c
d
print each param from "$*"
a b c d
print each param from "[email protected]"
a
b
c
d

命令替換

命令替換指的是將命令的輸出或者返回暫存在變數中,接下來通過輸出變數的形式,注意與閉包不同的是這個輸出會馬上獲得,不是接下來呼叫的時候才執行,示例如下:

a='12'
b=`echo $a`
a='34'
echo $b
#執行./test.sh
#輸出12

變數替換

變數 替換
${var} 變數本來的值
${var:-word} 如果變數 var 為空或已被刪除(unset),那麼返回 word,但不改變 var 的值。
${var:=word} 如果變數 var 為空或已被刪除(unset),那麼返回 word,並將 var 的值設定為 word。
${var:?message} 如果變數 var 為空或已被刪除(unset),那麼將訊息 message 送到標準錯誤輸出,可以用來檢測變數 var 是否可以被正常賦值。若此替換出現在Shell指令碼中,那麼指令碼將停止執行。
${var:+word} 如果變數 var 被定義,那麼返回 word,但不改變 var 的值。

運算子

shell 預設沒有數學運算子,可以使用expr來做數學運算

#!/bin/sh

a=10
b=20
v=`expr $a + $b`
echo "a+b:$v"

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

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

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

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

if [ $a == $b ]
then
    echo "a is euqal to b"
fi

if [ $a != $b ]
then
    echo "a is not equal to b"
fi
#輸出
a+b:30
a-b:-10
a\*b:200
b/a:2
b%a:0

運算子之間必須要有空格,可能是因為運算子是用函式實現的,賦值的=和變數之間不能有空格,有了空格就會被當成命令而不是變數,從而顯示沒有這個命令

shell單引號裡面不能引用變數,雙引號可以,這裡也實現了字串的拼接,

your_name='liuchenfei'
stra='single quote $your_name'
strb="double quote $your_name"
echo $stra
echo $strb
#輸出
single quote $your_name
double quote liuchenfei

${#str}可以計算字串的長度

your_name="liuchenfei"
echo ${#your_name}
#輸出
10

${str:m:n}提取字串m-n個字元

your_name="liuchenfei"
echo ${your_name:1:4}
#輸出
iuch

expr查詢字串

your_name="liuchenfei"
echo `expr index $liuchenfei chen`
#輸出
4

定義陣列

array_name=(value0,value1,…………)

array_name[0]=value0…………

訪問陣列

echo ${array_name[n]}#訪問第n個元素
echo ${array_name[*]}#訪問全部元素,@和*在這裡相同

${#list}和${list:m:n}也可以對陣列求長度和切片

echo “ff” > myfile 將輸出重定向到檔案myfile中,終端不再顯示輸出

可以使用printf 函式類似c語言printf 輸出

in="integer"
printf "%d is %s \n" 1  \$in
#輸出
1 is integer

if else 語句

shell if else語句的特點是在if下一行要加上then,結尾要加上fi
格式如下:

#if
if [ 條件 ]
then
    語句體
fi
#if else
if [ 條件 ]
then
    語句體
else
    語句體
fi
#if elif
if [條件]
then
    語句
elif [條件]
then
    語句
fi

比較表示式

表示式 含義 備註
-eq 檢測兩個數是否相等,相等返回 true。 [ $a -eq $b ] 返回 true。
-ne 檢測兩個數是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 檢測左邊的數是否大於右邊的,如果是,則返回 true。 [ $a -gt $b ] 返回 false。
-lt 檢測左邊的數是否小於右邊的,如果是,則返回 true。 [ $a -lt $b ] 返回 true。
-ge 檢測左邊的數是否大等於右邊的,如果是,則返回 true。 [ $a -ge $b ] 返回 false。
-le 檢測左邊的數是否小於等於右邊的,如果是,則返回 true。 [ $a -le $b ] 返回 true。

邏輯表示式

表示式 含義
-o
-a

多分支結構

類似switch-case的結構

read a
case a in
    1) echo "this is 1"
    ;;
    2) echo "this is 2"
    ;;
    *) echo "this is $a"
    ;;
esac
#執行
./sw.sh
1
#輸出
this is 1

for迴圈

for val in list
do
    語句
done

while迴圈

while [條件]
do
    語句
done

until 迴圈

#條件成立的時候還執行一次
until [條件]
do
    語句
done