1. 程式人生 > 實用技巧 >Shell程式設計入門

Shell程式設計入門

原文地址:https://zhuanlan.zhihu.com/p/102176365

Shell 是什麼?
Shell 是一個命令解釋權,它為使用者提供了一個向 Linux 核心傳送請求以便執行程式介面系統級程式,使用者可以用 Shell 來啟動、掛起、停止甚至是編寫一些程式。


Shell 程式設計快速入門
進入 Linux 終端,編寫一個 Shell 指令碼 hello.sh :

#!/bin/bash 
echo 'hello world!'


執行:

# 方法1 
sh hello.sh  

# 方法2 
chmod +x hello.sh 
./hello.sh


終端打印出 hello world!


說明:

  • #! 告訴系統這個指令碼需要什麼直譯器來執行。
  • 副檔名 .sh 不是強制要求的。
  • 方法1 直接執行直譯器,hello.sh 作為 Shell 直譯器的引數。此時 Shell 指令碼就不需要指定直譯器資訊,第一行可以去掉。
  • 方法2 hello.sh 作為可執行程式執行,Shell 指令碼第一行一定要指定直譯器。

Shell 變數
定義
Shell 變數分為系統變數自定義變數。系統變數有$HOME、$PWD、$USER等,顯示當前 Shell 中所有變數:set
變數名可以由字母、數字、下劃線組成,不能以數字開頭。
基本語法

  • 定義變數:變數名=變數值,等號兩側不能有空格,變數名一般習慣用大寫。
  • 刪除變數:unset 變數名 。
  • 宣告靜態變數:readonly 變數名,靜態變數不能unset。
  • 使用變數:$變數名

將命令返回值賦給變數(重點)

  • A=`ls` 反引號,執行裡面的命令
  • A=$(ls) 等價於反引號

Shell 環境變數
定義


基本語法

  1. export 變數名=變數值,將 Shell 變數輸出為環境變數。
  2. source 配置檔案路徑,讓修改後的配置資訊立即生效。
  3. echo $變數名,檢查環境變數是否生效

位置引數變數
基本語法

  • $n :$0 代表命令本身、$1-$9 代表第1到9個引數,10以上引數用花括號,如 ${10}。
  • $* :命令列中所有引數,且把所有引數看成一個整體。
  • $@ :命令列中所有引數,且把每個引數區分對待。
  • $# :所有引數個數。

例項:
編寫 Shell 指令碼 positionPara.sh ,輸出命令列輸入的各個引數資訊。

#!/bin/bash     
# 輸出各個引數 
echo $0 $1 $2 
echo $* 
echo $@ 
echo 引數個數=$#


執行:

chmod +x positionPara.sh 
./positionPara.sh 10 20


執行結果:

./positionPara.sh 10 20 
10 20 
10 20 
引數個數=2


預定義變數
定義
在賦值定義之前,事先在 Shell 指令碼中直接引用的變數。
基本語法

  • $$ :當前程序的 PID 程序號。
  • $! :後臺執行的最後一個程序的 PID 程序號。
  • $? :最後一次執行的命令的返回狀態,0為執行正確,非0執行失敗。

例項:
編寫 Shell 指令碼 prePara.sh ,輸出命令列輸入的各個引數資訊。

#!/bin/bash     
echo 當前的程序號=$$ 
# &:以後臺的方式執行程式 
./hello.sh & 
echo 最後一個程序的程序號=$! 
echo 最後執行的命令結果=$?


執行結果:

當前的程序號=41752 
最後一個程序的程序號=41753 
最後執行的命令結果=0 # hello world!


運算子
基本語法

  • $((運算式)) 或 $[運算式]
  • expr m + n 注意 expr 運算子間要有空格
  • expr m - n
  • expr \*,/,% 分別代表乘,除,取餘

例項

# 第1種方式 $(()) 
echo $(((2+3)*4))   

# 第2種方式 $[],推薦 
echo $[(2+3)*4]  

# 使用 expr 
TEMP=`expr 2 + 3` 
echo `expr $TEMP \* 4`


條件判斷
基本語法
[ condition ] 注意condition前後要有空格。非空返回0,0為 true,否則為 false 。
例項

#!/bin/bash 
if [ 'test01' = 'test' ] 
then
     echo '等於' 
fi  

# 20是否大於10 
if [ 20 -gt 10] 
then
     echo '大於' 
fi  

# 是否存在檔案/root/shell/a.txt 
if [ -e /root/shell/a.txt ] 
then
     echo '存在' 
fi  

if [ 'test02' = 'test02' ] && echo 'hello' || echo 'world' 
then
     echo '條件滿足,執行後面的語句' 
fi


執行結果:

大於 
hello 
條件滿足,執行後面的語句

流程控制

if 判斷

基本語法

if [ 條件判斷式 ];then   
    程式   
fi

# 或者(推薦)
if [ 條件判斷式 ]
then
    程式
elif [ 條件判斷式 ]
then
    程式
fi

例項

編寫 Shell 程式:如果輸入的引數大於60,輸出“及格”,否則輸出“不及格”。

#!/bin/bash
if [ $1 -ge 60 ]
then
    echo 及格
elif [ $1 -lt 60 ]
then
    echo "不及格" 
fi

case 分支

基本語法

case $變數名 in
"值1")
如果變數值等於值1,則執行此處程式1
;;
"值2")
如果變數值等於值2,則執行此處程式2
;;
...省略其它分支...
*)
如果變數值不等於以上列出的值,則執行此處程式
;;
esac

例項

當命令列引數為1時輸出“週一”,2時輸出“週二”,其他情況輸出“其它”。

case $1 in
"1")
echo 週一
;;
"2")
echo 週二
;;
*)
echo 其它
;;
esac

for 迴圈

基本語法

# 語法1
for 變數名 in 值1 值2 值3...
do
    程式
done

# 語法2
for ((初始值;迴圈控制條件;變數變化))
do
    程式
done

例項

  1. 列印命令列輸入的引數。
#!/bin/bash  

# 使用$* 
for i in "$*" 
do     
    echo "the arg is $i" 
done 
echo "=================="  

# 使用$@ 
for j in "$@" 
do     
    echo "the arg is $j" 
done

執行結果(回顧一下 $* 和 $@ 的區別):

the arg is 1 2 3 
================== 
the arg is 1 
the arg is 2 
the arg is 3

2. 輸出從1加到100的值。

#!/bin/bash 
SUM=0  
for ((i=1;i<=100;i++)) 
do     
    SUM=$[$SUM+$i] 
done 

echo $SUM

while 迴圈

基本語法

while [ 條件判斷式 ]
do
    程式
done 

例項

輸出從1加到100的值。

#!/bin/bash
SUM=0
i=0

while [ $i -le $1 ]
do
    SUM=$[$SUM+$i]
    i=$[$i+1]
done       
echo $SUM

讀取控制檯輸入

基本語法

read(選項)(引數)
選項

  • -p:指定讀取值時的提示符
  • -t:指定讀取值時等待的時間(秒),如果沒有在指定時間內輸入,就不再等待了。

引數

  • 變數名:讀取值的變數名

例項

讀取控制檯輸入一個num值。

#!/bin/bash

read -p "請輸入一個數num1=" NUM1
echo "你輸入num1的值是:$NUM1"

read -t 10 -p "請在10秒內輸入一個數num2=" NUM2
echo "你輸入num2的值是:$NUM2"

執行結果:

請輸入一個數num1=10
你輸入num1的值是:10
請在10秒內輸入一個數num2=20
你輸入num2的值是:20

函式

和其它程式語言一樣,Shell 程式設計有系統函式和自定義函式,本文只舉兩個常用系統函式。

系統函式

  • basename,刪掉路徑最後一個 / 前的所有部分(包括/),常用於獲取檔名。
    基本語法
    • basename [pathname] [suffix]
    • basename [string] [suffix]
    • 如果指定 suffix,也會刪掉pathname或string的字尾部分。

例項

# basename /usr/bin/sort  
sort  

# basename include/stdio.h  
stdio.h  

# basename include/stdio.h .h 
stdio
  • dirname,刪掉路徑最後一個 / 後的所有部分(包括/),常用於獲取檔案路徑。
    基本語法
    • dirname pathname
    • 如果路徑中不含 / ,則返回 '.' (當前路徑)。

例項

# dirname /usr/bin/  
/usr  

# dirname dir1/str dir2/str 
dir1 
dir2  

# dirname stdio.h 
.

自定義函式

基本語法

[ function ] funname[()]
{
    Action;
    [return int;]
}

# 呼叫
funname 引數1 引數2...

例項

計算輸入兩個引數的和。

#!/bin/bash

function getSum(){
    SUM=$[$n1+$n2]
    echo "sum=$SUM"
}   

read -p "請輸入第一個引數n1:" n1
read -p "請輸入第二個引數n2:" n2

# 呼叫 getSum 函式
getSum $n1 $n2