shell腳本基礎知識

mac終端下運行shell腳本

  • 寫好本身的腳本,好比aa.shhtml

  • 打開終端執行linux

    • 方法一:輸入命令./aa.shgit

    • 方法二:直接把aa.sh拖入到終端裏面github

注意事項:shell

  • 若是沒有成功報出問題:數組

    # Permission denied
    沒有權限
  • 解決辦法:修改該文件aa.sh的權限:bash

    chmod 777 aa.sh

而後再執行上面第二步的操做。markdown

變量

定義變量

# 變量名不加美圓符號
your_name="elaine"
# 從新定義
your_name="newname"
  • 首個字符必須爲字母(a-z,A-Z)。ssh

  • 中間不能有空格,可使用下劃線(_)。函數

  • 不能使用標點符號。

  • 不能使用bash裏的關鍵字(可用help命令查看保留關鍵字)。

只讀變量

#!/bin/bash
myUrl="http://lingmissing.github.io"
readonly myUrl
myUrl="http://www.google.com"

運行腳本,結果以下:

/bin/sh: NAME: This variable is read only.

使用變量

your_name="qinjx"
echo $your_name
echo ${your_name}
echo "your name is ${your_name}-l"

變量名外面的花括號是可選的,加不加都行,加花括號是爲了幫助解釋器識別變量的邊界。

刪除變量

unset variable_name

變量被刪除後不能再次使用。unset 命令不能刪除只讀變量。

#!/bin/sh
myUrl="http://lingmissing.github.io"
unset myUrl
echo $myUrl

變量類型

  • 局部變量:局部變量在腳本或命令中定義,僅在當前shell實例中有效,其餘shell啓動的程序不能訪問局部變量。

  • 環境變量:全部的程序,包括shell啓動的程序,都能訪問環境變量,有些程序須要環境變量來保證其正常運行。必要的時候shell腳本也能夠定義環境變量。

  • shell變量:shell變量是由shell程序設置的特殊變量。shell變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運行。

字符串

單引號

str='this is a string'
  • 單引號裏的任何字符都會原樣輸出,單引號字符串中的變量是無效的

  • 單引號字串中不能出現單引號(對單引號使用轉義符後也不行)

雙引號

your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"
  • 雙引號裏能夠有變量

  • 雙引號裏能夠出現轉義字符

拼接字符串

your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

獲取字符串長度

string="abcd"
echo ${#string} #輸出 4

提取子字符串

如下實例從字符串第 2 個字符開始截取 4 個字符:

string="runoob is a great site"
echo ${string:1:4} # 輸出 unoo

查找子字符串

查找字符 "i 或 s" 的位置:

string="runoob is a great company"
echo `expr index "$string" is`  # 輸出 8

數組

bash支持一維數組(不支持多維數組),而且沒有限定數組的大小。

定義數組

# 格式:數組名=(值1 值2 ... 值n)
array_name=(value0 value1 value2 value3)
# or 
array_name=(
value0
value1
value2
value3
)
# or
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

讀取數組

# 格式:${數組名[下標]}
valuen=${array_name[n]}
# 使用@符號能夠獲取數組中的全部元素
echo ${array_name[@]}

獲取數組的長度

# 取得數組元素的個數
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得數組單個元素的長度
lengthn=${#array_name[n]}

註釋

以"#"開頭的行就是註釋,會被解釋器忽略。

#--------------------------------------------
# 這是一個註釋
# author:elaine
# site:lingmissing.github.io
# slogan:學的不只是技術,更是夢想!
#--------------------------------------------
##### 用戶配置區 開始 #####
#
#
# 這裏能夠添加腳本描述信息
# 
#
##### 用戶配置區 結束  #####

參數傳遞

腳本內獲取參數的格式爲:$n。n 表明一個數字,1 爲執行腳本的第一個參數,2 爲執行腳本的第二個參數,以此類推……

echo "Shell 傳遞參數實例!";
echo "執行的文件名:$0";
echo "第一個參數爲:$1";
echo "第二個參數爲:$2";
echo "第三個參數爲:$3";

執行

$ ./test.sh 1 2 3
# print
執行的文件名:./test.sh
第一個參數爲:1
第二個參數爲:2
第三個參數爲:3
參數處理 說明
$# 傳遞到腳本的參數個數
$* 以一個單字符串顯示全部向腳本傳遞的參數。如"$*"用「"」括起來的狀況、以"$1 $2 … $n"的形式輸出全部參數。
$$ 腳本運行的當前進程ID號
$! 後臺運行的最後一個進程的ID號
$@ 與$*相同,可是使用時加引號,並在引號中返回每一個參數。如"$@"用「"」括起來的狀況、以"$1" "$2" … "$n" 的形式輸出全部參數。
$- 顯示Shell使用的當前選項,與set命令功能相同。
$? 顯示最後命令的退出狀態。0表示沒有錯誤,其餘任何值代表有錯誤。

基本運算

  • 算數運算符

  • 關係運算符

  • 布爾運算符

  • 字符串運算符

  • 文件測試運算符

expr 是一款表達式計算工具,使用它能完成表達式的求值操做。

#!/bin/bash
val=`expr 2 + 2`
echo "兩數之和爲 : $val"

執行腳本,輸出結果爲

兩數之和爲 : 4

注意:

  • 表達式和運算符之間要有空格

  • 完整的表達式要被 包含,注意這個字符不是經常使用的單引號

算術運算符

運算符 說明 舉例
+ 加法 `expr $a + $b`
- 減法 `expr $a - $b`
* 乘法 `expr $a * $b`
/ 除法 `expr $b / $a`
% 取餘 `expr $b % $a`
= 賦值 a=$b
== 等於 [ $a == $b ]
!= 不等於 [ $a != $b ]
#!/bin/sh

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

執行後輸出

a + b : 30
a - b : -10
a * b : 200
b / a : 2
b % a : 0
a 不等於 b
  • 乘號(*)前邊必須加反斜槓()才能實現乘法運算;

  • if...then...fi 是條件語句,後續將會講解。

  • 在 MAC 中 shell 的 expr 語法是:$((表達式)),此處表達式中的 "*" 不須要轉義符號 "" 。

關係運算符

運算符 說明 舉例
-eq 檢測兩個數是否相等,相等返回 true。 [ $a -eq $b ]
-ne 檢測兩個數是否相等,不相等返回 true。 [ $a -ne $b ]
-gt 檢測左邊的數是否大於右邊的,若是是,則返回 true。 [ $a -gt $b ]
-lt 檢測左邊的數是否小於右邊的,若是是,則返回 true。 [ $a -lt $b ]
-ge 檢測左邊的數是否大於等於右邊的,若是是,則返回 true。 [ $a -ge $b ]
-le 檢測左邊的數是否小於等於右邊的,若是是,則返回 true。 [ $a -le $b ]

布爾運算符

運算符 說明 舉例
! 非運算 [ ! false ]
-o 或運算 [ $a -lt 20 -o $b -gt 100 ]
-a 與運算 [ $a -lt 20 -a $b -gt 100 ]

邏輯運算符

因爲在markdown中||被識別成表格分割,在此以O代替。

運算符 說明 舉例
&& 邏輯的 AND [[ $a -lt 100 && $b -gt 100 ]]
O 邏輯的 OR [[ $a -lt 100 O $b -gt 100 ]]

字符串運算符

運算符 說明 舉例
= 檢測兩個字符串是否相等,相等返回 true。 [ $a = $b ]
!= 檢測兩個字符串是否相等,不相等返回 true。 [ $a != $b ]
-z 檢測字符串長度是否爲0,爲0返回 true。 [ -z $a ]
-n 檢測字符串長度是否爲0,不爲0返回 true。 [ -n $a ]
str 檢測字符串是否爲空,不爲空返回 true。 [ $a ]

文件測試運算符

運算符 說明 舉例
-b file 檢測文件是不是塊設備文件,若是是,則返回 true。 [ -b $file ]
-c file 檢測文件是不是字符設備文件,若是是,則返回 true。 [ -c $file ]
-d file 檢測文件是不是目錄,若是是,則返回 true。 [ -d $file ]
-f file 檢測文件是不是普通文件(既不是目錄,也不是設備文件),若是是,則返回 true。 [ -f $file ]
-g file 檢測文件是否設置了 SGID 位,若是是,則返回 true。 [ -g $file ]
-k file 檢測文件是否設置了粘着位(Sticky Bit),若是是,則返回 true。 [ -k $file ]
-p file 檢測文件是不是有名管道,若是是,則返回 true。 [ -p $file ]
-u file 檢測文件是否設置了 SUID 位,若是是,則返回 true。 [ -u $file ]
-r file 檢測文件是否可讀,若是是,則返回 true。 [ -r $file ]
-w file 檢測文件是否可寫,若是是,則返回 true。 [ -w $file ]
-x file 檢測文件是否可執行,若是是,則返回 true。 [ -x $file ]
-s file 檢測文件是否爲空(文件大小是否大於0),不爲空返回 true。 [ -s $file ]
-e file 檢測文件(包括目錄)是否存在,若是是,則返回 true。 [ -e $file ]
#!/bin/sh
file="/var/www/runoob/test.sh"
if [ -r $file ]
then
   echo "文件可讀"
else
   echo "文件不可讀"
fi
if [ -w $file ]
then
   echo "文件可寫"
else
   echo "文件不可寫"
fi
if [ -x $file ]
then
   echo "文件可執行"
else
   echo "文件不可執行"
fi
if [ -f $file ]
then
   echo "文件爲普通文件"
else
   echo "文件爲特殊文件"
fi
if [ -d $file ]
then
   echo "文件是個目錄"
else
   echo "文件不是個目錄"
fi
if [ -s $file ]
then
   echo "文件不爲空"
else
   echo "文件爲空"
fi
if [ -e $file ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi

執行腳本,輸出結果以下所示:

文件可讀
文件可寫
文件可執行
文件爲普通文件
文件不是個目錄
文件不爲空
文件存在

echo命令

  • 顯示普通字符串:

    echo "It is a test"
    # or
    echo It is a test
  • 顯示轉義字符

    echo "\"It is a test\""
  • 顯示變量

    echo "$name It is a teset"
  • 顯示換行

    echo -e "OK! \n" # -e 開啓轉義
  • 顯示不換行

    echo -e "OK! \c" # -e 開啓轉義 \c 不換行
  • 原樣輸出字符串

    echo '$name\"'
  • 顯示執行結果

    echo `date`
    echo `date +%Y%m%d`

擴展:打印帶顏色的字符串

# 字體色彩的選項說明
echo "\033[30m 黑色字 \033[0m"
echo "\033[31m 紅色字 \033[0m"
echo "\033[32m 綠色字 \033[0m"
echo "\033[33m 黃色字 \033[0m"
echo "\033[34m 藍色字 \033[0m"
echo "\033[35m 紫色字 \033[0m"
echo "\033[36m 天藍字 \033[0m"
echo "\033[37m 白色字 \033[0m"
 
echo "\033[40;37m 黑底白字 \033[0m"
echo "\033[41;37m 紅底白字 \033[0m"
echo "\033[42;37m 綠底白字 \033[0m"
echo "\033[43;37m 黃底白字 \033[0m"
echo "\033[44;37m 藍底白字 \033[0m"
echo "\033[45;37m 紫底白字 \033[0m"
echo "\033[46;37m 天藍底白字 \033[0m"
echo "\033[47;30m 白底黑字 \033[0m"

# 控制選項說明 
\33[0m 關閉全部屬性
\33[1m 設置高亮度
\33[4m 下劃線
\33[5m 閃爍
\33[7m 反顯
\33[8m 消隱
\33[30m -- \33[37m 設置前景色
\33[40m -- \33[47m 設置背景色
\33[nA 光標上移n行
\33[nB 光標下移n行
\33[nC 光標右移n行
\33[nD 光標左移n行
\33[y;xH設置光標位置
\33[2J 清屏
\33[K 清除從光標到行尾的內容
\33[s 保存光標位置
\33[u 恢復光標位置
\33[?25l 隱藏光標
\33[?25h 顯示光標

printf 命令

printf  format-string  [arguments...]

參數說明:

  • format-string: 爲格式控制字符串

  • arguments: 爲參數列表。

默認printf不會像 echo 自動添加換行符,咱們能夠手動添加 n。

$ echo "Hello, Shell"
Hello, Shell
$ printf "Hello, Shell\n"
Hello, Shell
$
轉義序列 說明
a 警告字符,一般爲ASCII的BEL字符
b 後退
c 抑制(不顯示)輸出結果中任何結尾的換行字符(只在%b格式指示符控制下的參數字符串中有效),並且,任何留在參數裏的字符、任何接下來的參數以及任何留在格式字符串中的字符,都被忽略
f 換頁(formfeed)
n 換行
r 回車(Carriage return)
t 水平製表符
v 垂直製表符
\ 一個字面上的反斜槓字符
ddd 表示1到3位數八進制值的字符。僅在格式字符串中有效
0ddd 表示1到3位的八進制值字符
#!/bin/sh
printf "%-10s %-8s %-4s\n" 姓名 性別 體重kg  
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234 
printf "%-10s %-8s %-4.2f\n" 楊過 男 48.6543 
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

執行腳本,輸出結果以下所示:

姓名     性別   體重kg
郭靖     男      66.12
楊過     男      48.65
郭芙     女      47.99

%s %c %d %f都是格式替代符
%-10s 指一個寬度爲10個字符(-表示左對齊,沒有則表示右對齊),任何字符都會被顯示在10個字符寬的字符內,若是不足則自動以空格填充,超過也會將內容所有顯示出來。
%-4.2f 指格式化爲小數,其中.2指保留2位小數。

test命令

num1=100
num2=100
if test $[num1] -eq $[num2]
then
    echo '兩個數相等!'
else
    echo '兩個數不相等!'
fi

流程控制

if語句

# if
if condition
then
    command1 
    command2
    ...
    commandN 
fi
# or 
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
# if else 
if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi
# if else-if else
if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

for循環

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
# or
for var in item1 item2 ... itemN; do command1; command2… done;

例如

# 循環數字
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done
# 循環字符串
for str in 'This is a string'
do
    echo $str
done

while語句

while循環執行一系列命令直至條件爲假時中止。

while condition
do
    command
done
# 案例
#!/bin/sh
int=1
while(( $int<=5 ))
do
        echo $int
        let "int++"
done

until 循環

until循環執行一系列命令直至條件爲真時中止。

until condition
do
    command
done

case語句

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac
#!/bin/sh
echo '輸入 1 到 4 之間的數字:'
echo '你輸入的數字爲:'
read aNum
case $aNum in
    1)  echo '你選擇了 1'
    ;;
    2)  echo '你選擇了 2'
    ;;
    3)  echo '你選擇了 3'
    ;;
    4)  echo '你選擇了 4'
    ;;
    *)  echo '你沒有輸入 1 到 4 之間的數字'
    ;;
esac

break

break命令容許跳出全部循環(終止執行後面的全部循環)。

#!/bin/sh
while :
do
    echo -n "輸入 1 到 5 之間的數字:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你輸入的數字爲 $aNum!"
        ;;
        *) echo "你輸入的數字不是 1 到 5 之間的! 遊戲結束"
            break
        ;;
    esac
done

continue

continue命令與break命令相似,只有一點差異,它不會跳出全部循環,僅僅跳出當前循環。

#!/bin/sh
while :
do
    echo -n "輸入 1 到 5 之間的數字: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你輸入的數字爲 $aNum!"
        ;;
        *) echo "你輸入的數字不是 1 到 5 之間的!"
            continue
            echo "遊戲結束"
        ;;
    esac
done

esac

case語法須要一個esac(就是case反過來)做爲結束標記,每一個case分支用右圓括號,用兩個分號表示break。

函數

[ function ] funname [()]

{

    action;

    [return int;]

}
#!/bin/sh
demoFun(){
    echo "這是個人第一個 shell 函數!"
}
echo "-----函數開始執行-----"
demoFun
echo "-----函數執行完畢-----"
#!/bin/bash
funWithReturn(){
    echo "這個函數會對輸入的兩個數字進行相加運算..."
    echo "輸入第一個數字: "
    read aNum
    echo "輸入第二個數字: "
    read anotherNum
    echo "兩個數字分別爲 $aNum 和 $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "輸入的兩個數字之和爲 $? !"

函數參數

funWithParam(){
    echo "第一個參數爲 $1 !"
    echo "第二個參數爲 $2 !"
    echo "第十個參數爲 $10 !"
    echo "第十個參數爲 ${10} !"
    echo "第十一個參數爲 ${11} !"
    echo "參數總數有 $# 個!"
    echo "做爲一個字符串輸出全部參數 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

經常使用系統自帶命令

  • mkdir 建立文件夾

  • touch 建立文件

  • mvdir 移動或重命名目錄

  • zip 壓縮文件

    zip -q -r -e -m -o [yourName].zip someThing

-q 表示不顯示壓縮進度狀態
-r 表示子目錄子文件所有壓縮爲zip //這部比較重要,否則的話只有something這個文件夾被壓縮,裏面的沒有被壓縮進去
-e 表示你的壓縮文件須要加密,終端會提示你輸入密碼的
-m 表示壓縮完刪除原文件
-o 表示設置全部被壓縮文件的最後修改時間爲當前壓縮時間

結合系統自帶的命令(點擊查閱

#!/bin/sh
mkdir shell_tut
cd shell_tut

for ((i=0; i<10; i++)); do
    touch test_$i.txt
done

轉載自 菜鳥教程

相關文章
相關標籤/搜索