# 音視頻學習 (五) Shell 腳本入門
## 前言
學習 Shell 腳本也是為了后面編譯第三方庫打下一個基礎,編譯第三方庫幾乎都需要用到 shell 語法,如果你不懂那么就不會編譯出自己想要的版本,只會 copy 網絡上別人寫好的這其實是沒有任何學習的意義。
下面我們就先來學習 Shell 語法基礎。等到后續編譯 FFmpeg 庫有不明白的在詳細介紹。
## 介紹
Shell 是一個用 C 語言編寫的程序,它是用戶使用 Linux 的橋梁。Shell 既是一種命令語言,又是一種程序設計語言。
Shell 是指一種應用程序,這個應用程序提供了一個界面,用戶通過這個界面訪問操作系統內核的服務。
Ken Thompson 的 sh 是第一種 Unix Shell,Windows Explorer 是一個典型的圖形界面 Shell。
## Shell 入門學習
打開文本編輯器(可以使用 vi/vim 命令來創建文件),新建一個文件 test.sh,擴展名為 sh(sh代表shell),擴展名并不影響腳本執行,見名知意就好。
### 第一個 shell 腳本
我們還是以輸出一個 “Hello Word !” 為例子正式進行學習,腳本代碼如下:
~~~
#!/bin/bash
echo "Hello World !"
復制代碼
~~~
輸出:

**#!**是一個約定的標記,它告訴系統這個腳本需要什么解釋器來執行,即使用哪一種 Shell。
echo 命令用于向窗口輸出文本。
注意: 如果執行提示沒有權限還需要命令輸入`chmod +x test.sh`開放可執行權限。
### 變量
定義變量時,變量名不加美元符號 ($) ,如下:
~~~
my_name="DevYK"
復制代碼
~~~
注意,變量名和等號之間不能有空格,這可能和你熟悉的所有編程語言都不一樣。同時,變量名的命名須遵循如下規則:
* 命名只能使用英文字母,數字和下劃線,首個字符不能以數字開頭。
* 中間不能有空格,可以使用下劃線(\_)。
* 不能使用標點符號。
* 不能使用bash里的關鍵字(可用help命令查看保留關鍵字)。
除了顯式地直接賦值,還可以用語句給變量賦值,如:
~~~
#一定要切記for file in $后邊的那個引號不是單引號,而是tab鍵上邊的那個鍵,或者說是1左邊的那個鍵。否則的話不起作用。
for file in $`ls /root/android`
do
echo $file
done
復制代碼
~~~
輸出效果:

**使用變量:**
使用一個定義過的變量,只要在變量名前面加美元符號即可,如:
~~~
my_name="DevYK"
echo $my_name
#變量名外面的花括號是可選的,加不加都行,加花括號是為了幫助解釋器識別變量的邊界
echo ${my_name}
復制代碼
~~~
輸出:
~~~
DevYK
DevYK
復制代碼
~~~
**只讀變量:**
~~~
#4. 只讀變量
my_blog_url="https://www.devyk.top/"
readonly my_blog_url
my_blog_url="www.baidu.com"
復制代碼
~~~
輸出:

**刪除變量:**
~~~
#變量被刪除后不能再次使用。unset 命令不能刪除只讀變量。
your_name="小明"
unset your_name
echo $your_name
復制代碼
~~~
輸出:

可以看到定義了刪除變量之后,后面是沒有任何輸出
**變量類型:**
運行shell時,會同時存在三種變量:
* **1) 局部變量**局部變量在腳本或命令中定義,僅在當前 shell 實例中有效,其他 shell 啟動的程序不能訪問局部變量。
* **2) 環境變量**所有的程序,包括 shell 啟動的程序,都能訪問環境變量,有些程序需要環境變量來保證其正常運行。必要的時候 shell 腳本也可以定義環境變量。
* **3) shell變量**shell 變量是由 shell 程序設置的特殊變量。shell 變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運行
### 字符串
字符串是 shell 編程中最常用最有用的數據類型(除了數字和字符串,也沒啥其它類型好用了),字符串可以用單引號,也可以用雙引號,也可以不用引號。
~~~
#單引號
str='this is a book'
復制代碼
~~~
單引號字符串的限制:
* 單引號里的任何字符都會原樣輸出,單引號字符串中的變量是無效的;
* 單引號字串中不能出現單獨一個的單引號(對單引號使用轉義符后也不行),但可成對出現,作為字符串拼接使用。
~~~
#雙引號
your_title=“玄幻小說”
str="嗨, 請問這是一本什么類型的小說? \"$your_title\" \n"
echo -e $str
復制代碼
~~~
輸出:
~~~
嗨, 請問這是一本什么類型的小說? "“玄幻小說”"
復制代碼
~~~
雙引號的優點:
* 雙引號里可以有變量
* 雙引號里可以出現轉義字符
**拼接字符串:**
~~~
your_name="DevYK_1"
#使用雙引號拼接
str1="2 我是 “$your_name” !"
str2="2 我是 ${your_name} !"
echo $str1 $str2
#使用單引號拼接
str3='1 我是 “$your_name” !'
str4='1 我是 ${your_name} !'
echo $str3 $str4
復制代碼
~~~
輸出:
~~~
2 我是 “DevYK_1” ! 2 我是 DevYK_1 !
1 我是 DevYK_1 ! 1 我是 ${your_name} !
復制代碼
~~~
**獲取字符串長度:**
~~~
str_length='123456'
echo ${#str_length}
復制代碼
~~~
輸出: 6
**提取字符串:**
以下實例從字符串第**2**個字符開始截取**4**個字符:
~~~
echo ${str_length:1:4}
復制代碼
~~~
輸出: 2345
**查找字符串:**
~~~
echo `expr index "$str_length" 3` //是反斜杠 tab 上 1 鍵左
復制代碼
~~~
輸出:3
### 傳遞參數
我們可以在執行 Shell 腳本時,向腳本傳遞參數,腳本內獲取參數的格式為:**$n**。**n**代表一個數字,1 為執行腳本的第一個參數,2 為執行腳本的第二個參數,以此類推……
例子:
以下實例我們向腳本傳遞三個參數,并分別輸出,其中**$0**為執行的文件名:
~~~
echo "Shell 傳遞參數實例!";
echo "執行的文件名:$0";
echo "第一個參數為:$1";
echo "第二個參數為:$2";
echo "第三個參數為:$3";
復制代碼
~~~
輸出:

### 數組
數組中可以存放多個值。Bash Shell 只支持一維數組(不支持多維數組),初始化時不需要定義數組大小。
與大部分編程語言類似,數組元素的下標由 0 開始。
Shell 數組用括號來表示,元素用 "空格" 符號分割開,語法格式如下:
~~~
array_name=(value1 ... valuen)
復制代碼
~~~
例子:
~~~
my_array=(A B "C" D)
echo "第一個元素為: ${my_array[0]}"
echo "第二個元素為: ${my_array[1]}"
echo "第三個元素為: ${my_array[2]}"
echo "第四個元素為: ${my_array[3]}"
#使用@ 或 * 可以獲取數組中的所有元素,例如:
echo "數組的元素為: ${my_array[*]}"
echo "數組的元素為: ${my_array[@]}"
#獲取數組長度的方法與獲取字符串長度的方法相同
echo "數組元素個數為: ${#my_array[*]}"
echo "數組元素個數為: ${#my_array[@]}"
復制代碼
~~~
輸出:
~~~
第一個元素為: A
第二個元素為: B
第三個元素為: C
第四個元素為: D
數組的元素為: A B C D
數組的元素為: A B C D
數組元素個數為: 4
數組元素個數為: 4
復制代碼
~~~
### 運算符
Shell 和其他編程語言一樣,支持多種運算符,包括:
* 算數運算符
* 關系運算符
* 布爾運算符
* 字符串運算符
* 文件測試運算符
原生 bash 不支持簡單的數學運算,但是可以通過其他命令來實現,例如 awk 和 expr,expr 最常用。
expr 是一款表達式計算工具,使用它能完成表達式的求值操作。
**注意:**
* 表達式和運算符之間要有空格,例如 2+2 是不對的,必須寫成 2 + 2,這與我們熟悉的大多數編程語言不一樣。
* 完整的表達式要被包含,注意這個字符不是常用的單引號,在 Esc 鍵下邊。
**算符運算符:**
| 運算符 | 說明 | 舉例 |
| --- | --- | --- |
| + | 加法 | `expr $a + $b`結果為 30。 |
| \- | 減法 | `expr $a - $b`結果為 -10。 |
| \* | 乘法 | `expr $a \* $b`結果為 200。 |
| / | 除法 | `expr $b / $a`結果為 2。 |
| % | 取余 | `expr $b % $a`結果為 0。 |
| \= | 賦值 | a=$b 將把變量 b 的值賦給 a。 |
| \== | 相等。用于比較兩個數字,相同則返回 true。 | \[ $a == $b \] 返回 false。 |
| != | 不相等。用于比較兩個數字,不相同則返回 true。 | \[ $a != $b \] 返回 true。 |
\*\*注意:\*\*條件表達式要放在方括號之間,并且要有空格,例如:**\[$a==$b\]**是錯誤的,必須寫成**\[ $a == $b \]**。
~~~
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 語法是:**$((表達式))**,此處表達式中的 "\*" 不需要轉義符號 "" 。
**關系運算符:**
關系運算符只支持數字,不支持字符串,除非字符串的值是數字。
下表列出了常用的關系運算符,假定變量 a 為 10,變量 b 為 20:
| 運算符 | 說明 | 舉例 |
| --- | --- | --- |
| \-eq | 檢測兩個數是否相等,相等返回 true。 | \[ $a -eq $b \] 返回 false。 |
| \-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。 |
例子:
~~~
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi
復制代碼
~~~
輸出:
~~~
10 -eq 20: a 不等于 b
10 -ne 20: a 不等于 b
10 -gt 20: a 不大于 b
10 -lt 20: a 小于 b
10 -ge 20: a 小于 b
10 -le 20: a 小于或等于 b
復制代碼
~~~
**布爾運算符:**
下表列出了常用的布爾運算符,假定變量 a 為 10,變量 b 為 20:
| 運算符 | 說明 | 舉例 |
| --- | --- | --- |
| ! | 非運算,表達式為 true 則返回 false,否則返回 true。 | \[ ! false \] 返回 true。 |
| \-o | 或運算,有一個表達式為 true 則返回 true。 | \[ $a -lt 20 -o $b -gt 100 \] 返回 true。 |
| \-a | 與運算,兩個表達式都為 true 才返回 true。 | \[ $a -lt 20 -a $b -gt 100 \] 返回 false。 |
~~~
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
復制代碼
~~~
輸出:
~~~
10 != 20 : a 不等于 b
10 小于 100 且 20 大于 15 : 返回 true
10 小于 100 或 20 大于 100 : 返回 true
10 小于 5 或 20 大于 100 : 返回 false
復制代碼
~~~
**邏輯運算符:**
以下介紹 Shell 的邏輯運算符,假定變量 a 為 10,變量 b 為 20:
| 運算符 | 說明 | 舉例 |
| --- | --- | --- |
| && | 邏輯的 AND | \[\[ $Misplaced &a -lt 100 && $b -gt 100 \]\] 返回 false |
| || | 邏輯的 OR | \[\[ $a -lt 100 |
例子:
~~~
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
復制代碼
~~~
輸出:
~~~
返回 false
返回 true
復制代碼
~~~
**字符串運算符**
下表列出了常用的字符串運算符,假定變量 a 為 "123",變量 b 為 "456":
| 運算符 | 說明 | 舉例 |
| --- | --- | --- |
| \= | 檢測兩個字符串是否相等,相等返回 true。 | \[ $a = $b \] 返回 false。 |
| != | 檢測兩個字符串是否相等,不相等返回 true。 | \[ $a != $b \] 返回 true。 |
| \-z | 檢測字符串長度是否為0,為0返回 true。 | \[ -z $a \] 返回 false。 |
| \-n | 檢測字符串長度是否為0,不為0返回 true。 | \[ -n "$a" \] 返回 true。 |
| $ | 檢測字符串是否為空,不為空返回 true。 | \[ $a \] 返回 true。 |
例子:
~~~
str1="123"
str2="456"
if [ $str1 = $str2 ]
then
echo "$str1 = $str2 : str1 等于 str2"
else
echo "$str1 = $str2: str1 不等于 str2"
fi
if [ $str1 != $str2 ]
then
echo "$str1 != $str2 : str1 不等于 str2"
else
echo "$str1 != $str2: str1 等于 str2"
fi
if [ -z $str1 ]
then
echo "-z $str1 : 字符串長度為 0"
else
echo "-z $str1 : 字符串長度不為 0"
fi
if [ -n "$str1" ]
then
echo "-n $str1 : 字符串長度不為 0"
else
echo "-n $str1 : 字符串長度為 0"
fi
if [ $str1 ]
then
echo "$str1 : 字符串不為空"
else
echo "$str1 : 字符串為空"
fi
復制代碼
~~~
輸出:
~~~
123 = 456: str1 不等于 str2
123 != 456 : str1 不等于 str2
-z 123 : 字符串長度不為 0
-n 123 : 字符串長度不為 0
123 : 字符串不為空
復制代碼
~~~
**文件測試運算符:**
文件測試運算符用于檢測 Unix 文件的各種屬性。
屬性檢測描述如下:
| 操作符 | 說明 | 舉例 |
| --- | --- | --- |
| \-b file | 檢測文件是否是塊設備文件,如果是,則返回 true。 | \[ -b $file \] 返回 false。 |
| \-c file | 檢測文件是否是字符設備文件,如果是,則返回 true。 | \[ -c $file \] 返回 false。 |
| \-d file | 檢測文件是否是目錄,如果是,則返回 true。 | \[ -d $file \] 返回 false。 |
| \-f file | 檢測文件是否是普通文件(既不是目錄,也不是設備文件),如果是,則返回 true。 | \[ -f $file \] 返回 true。 |
| \-g file | 檢測文件是否設置了 SGID 位,如果是,則返回 true。 | \[ -g $file \] 返回 false。 |
| \-k file | 檢測文件是否設置了粘著位(Sticky Bit),如果是,則返回 true。 | \[ -k $file \] 返回 false。 |
| \-p file | 檢測文件是否是有名管道,如果是,則返回 true。 | \[ -p $file \] 返回 false。 |
| \-u file | 檢測文件是否設置了 SUID 位,如果是,則返回 true。 | \[ -u $file \] 返回 false。 |
| \-r file | 檢測文件是否可讀,如果是,則返回 true。 | \[ -r $file \] 返回 true。 |
| \-w file | 檢測文件是否可寫,如果是,則返回 true。 | \[ -w $file \] 返回 true。 |
| \-x file | 檢測文件是否可執行,如果是,則返回 true。 | \[ -x $file \] 返回 true。 |
| \-s file | 檢測文件是否為空(文件大小是否大于0),不為空返回 true。 | \[ -s $file \] 返回 true。 |
| \-e file | 檢測文件(包括目錄)是否存在,如果是,則返回 true。 | \[ -e $file \] 返回 true。 |
其他檢查符:
* **\-S**: 判斷某文件是否 socket。
* **\-L**: 檢測文件是否存在并且是一個符號鏈接。
變量 file 表示文件**/root/android/shell/test.sh**,它具有**rwx**權限。下面的代碼,將檢測該文件的各種屬性:
~~~
file="/root/android/shell/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 命令
Shell 的 echo 指令用于字符串的輸出。命令格式:
~~~
echo string
復制代碼
~~~
例子
~~~
#顯示普通字符串
echo "This is a book"
#也可以省略雙引號
echo This is a book
#顯示轉義字符
echo"\"This is a book"\"
#顯示變量
your_name_2="DevYK_2"
echo "變量的名稱是:$your_name_2"
#顯示換行 -e 開始轉義
echo -e "換行 \n"
echo "是否換行了"
#顯示不換行
echo -e "不換行 \c"
echo "是否換行了"
#顯示命令執行結果
echo `date`
復制代碼
~~~
輸出:
~~~
This is a book
This is a book
"This is a book"
變量的名稱是:DevYK_2
換行
是否換行了
不換行 是否換行了
Mon Jan 13 12:12:32 CST 2020
復制代碼
~~~
### printf 命令
上一章節我們學習了 Shell 的 echo 命令,本章節我們來學習 Shell 的另一個輸出命令 printf。
printf 命令模仿 C 程序庫(library)里的 printf() 程序。
printf 由 POSIX 標準所定義,因此使用 printf 的腳本比使用 echo 移植性好。
printf 使用引用文本或空格分隔的參數,外面可以在 printf 中使用格式化字符串,還可以制定字符串的寬度、左右對齊方式等。默認 printf 不會像 echo 自動添加換行符,我們可以手動添加 \\n。
printf 命令的語法:
~~~
printf format-string [arguments...]
復制代碼
~~~
**參數說明:**
* **format-string:**為格式控制字符串
* **arguments:**為參數列表。
例子:
~~~
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 命令
Shell中的 test 命令用于檢查某個條件是否成立,它可以進行數值、字符和文件三個方面的測試。
**數值測試:**
| 參數 | 說明 |
| --- | --- |
| \-eq | 等于則為真 |
| \-ne | 不等于則為真 |
| \-gt | 大于則為真 |
| \-ge | 大于等于則為真 |
| \-lt | 小于則為真 |
| \-le | 小于等于則為真 |
例子:
~~~
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '兩個數相等!'
else
echo '兩個數不相等!'
fi
復制代碼
~~~
輸出:
~~~
兩個數相等!
復制代碼
~~~
**字符串測試:**
| 參數 | 說明 |
| --- | --- |
| \= | 等于則為真 |
| != | 不相等則為真 |
| \-z 字符串 | 字符串的長度為零則為真 |
| \-n 字符串 | 字符串的長度不為零則為真 |
例子:
~~~
name_="DEVYK"
name2_="DevYK"
if test $name_ = $name2_
then
echo '兩個字符串相等!'
else
echo '兩個字符串不相等!'
fi
復制代碼
~~~
輸出:
~~~
兩個字符串不相等!
復制代碼
~~~
**文件測試:**
| 參數 | 說明 |
| --- | --- |
| \-e 文件名 | 如果文件存在則為真 |
| \-r 文件名 | 如果文件存在且可讀則為真 |
| \-w 文件名 | 如果文件存在且可寫則為真 |
| \-x 文件名 | 如果文件存在且可執行則為真 |
| \-s 文件名 | 如果文件存在且至少有一個字符則為真 |
| \-d 文件名 | 如果文件存在且為目錄則為真 |
| \-f 文件名 | 如果文件存在且為普通文件則為真 |
| \-c 文件名 | 如果文件存在且為字符型特殊文件則為真 |
| \-b 文件名 | 如果文件存在且為塊特殊文件則為真 |
例子:
~~~
if test -e ./test.sh
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
復制代碼
~~~
輸出:
~~~
文件已存在!
復制代碼
~~~
### 流程控制
和 Java 語言不一樣,sh 的流程控制不可為空,如(以下為Java流程控制寫法):
~~~
if(1 == 2){
add(1,2)
}else{
//不做任何處理
}
復制代碼
~~~
在sh/bash里可不能這么寫,如果else分支沒有語句執行,就不要寫這個else。
**if 語句語法格式:**
~~~
if condition
then
command1
command2
...
commandN
fi
復制代碼
~~~
寫成一行(適用于終端命令提示符):
~~~
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
復制代碼
~~~
**for 循環:**
~~~
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
復制代碼
~~~
例子:
~~~
for loop in 1 2 3
do
echo "the value is $loop"
done
復制代碼
~~~
輸出:
~~~
the value is 1
the value is 2
the value is 3
復制代碼
~~~
**while 語句**
while 循環用于不斷執行一系列命令,也用于從輸入文件中讀取數據;命令通常為測試條件。其格式為:
~~~
while condition
do
command
done
復制代碼
~~~
以下是一個基本的 while 循環,測試條件是:如果 int 小于等于 5,那么條件返回真。int 從 0 開始,每次循環處理時,int 加 1 。運行上述腳本,返回數字 1 到 5 ,然后終止。
~~~
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
復制代碼
~~~
輸出:
~~~
1
2
3
4
5
復制代碼
~~~
**無限循環**
無限循環語法格式:
~~~
while :
do
command
done
復制代碼
~~~
或者:
~~~
while true
do
command
done
復制代碼
~~~
或者:
~~~
for (( ; ; ))
復制代碼
~~~
### 函數
linux shell 可以用戶定義函數,然后在 shell 腳本中可以隨便調用。
shell 中函數的定義格式如下:
~~~
[ function ] funname [()]
{
action;
[return int;]
}
復制代碼
~~~
說明:
* 1、可以帶 function fun() 定義,也可以直接 fun() 定義,不帶任何參數。
* 2、參數返回,可以顯示加:return 返回,如果不加,將以最后一條命令運行結果,作為返回值。 return 后跟數值 n(0-255)
例子:
~~~
funWithReturn(){
echo "這個函數會對輸入的兩個數字進行相加運算..."
echo "輸入第一個數字: "
read aNum
echo "輸入第二個數字: "
read anotherNum
echo "兩個數字分別為 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "輸入的兩個數字之和為 $? !"
復制代碼
~~~
輸出:
~~~
這個函數會對輸入的兩個數字進行相加運算...
輸入第一個數字:
12
輸入第二個數字:
22
兩個數字分別為 12 和 22 !
輸入的兩個數字之和為 34 !
復制代碼
~~~
函數返回值在調用該函數后通過 $? 來獲得。
注意:所有函數在使用前必須定義。這意味著必須將函數放在腳本開始部分,直至 shell 解釋器首次發現它時,才可以使用。調用函數僅使用其函數名即可。
**函數參數:**
在 Shell 中,調用函數時可以向其傳遞參數。在函數體內部,通過 $n 的形式來獲取參數的值,例如,$1表示第一個參數,$2表示第二個參數...
例子:
~~~
funWithParam(){
echo "第一個參數為 $1 !"
echo "第二個參數為 $2 !"
echo "第十個參數為 $10 !"
echo "第十個參數為 ${10} !"
echo "第十一個參數為 ${11} !"
echo "參數總數有 $# 個!"
echo "作為一個字符串輸出所有參數 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 22 11
復制代碼
~~~
輸出:
~~~
第一個參數為 1 !
第二個參數為 2 !
第十個參數為 10 !
第十個參數為 22 !
第十一個參數為 11 !
參數總數有 11 個!
作為一個字符串輸出所有參數 1 2 3 4 5 6 7 8 9 22 11 !
復制代碼
~~~
注意,$10 不能獲取第十個參數,獲取第十個參數需要?${10}。當n>=10時,需要使用${n}來獲取參數。
另外,還有幾個特殊字符用來處理參數:
| 參數處理 | 說明 |
| --- | --- |
| $# | 傳遞到腳本或函數的參數個數 |
| $\* | 以一個單字符串顯示所有向腳本傳遞的參數 |
| ? | 腳本運行的當前進程ID號 |
| $! | 后臺運行的最后一個進程的ID號 |
| $@ | 與$\*相同,但是使用時加引號,并在引號中返回每個參數。 |
| $- | 顯示Shell使用的當前選項,與set命令功能相同。 |
| $? | 顯示最后命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。 |
## 總結
Shell 入門知識就介紹這么多,后續編譯第三方庫編寫 Shell 腳本有陌生的在進行介紹。
## 參考
* [Shell 教程](https://www.runoob.com/linux/linux-shell-basic-operators.html)
* [Linux 命令](https://www.runoob.com/linux/linux-command-manual.html)
- 前言
- JNI基礎知識
- C語言知識點總結
- ①基本語法
- ②數據類型
- 枚舉類型
- 自定義類型(類型定義)
- ③格式化輸入輸出
- printf函數
- scanf函數
- 編程規范
- ④變量和常量
- 局部變量和外部變量
- ⑤類型轉換
- ⑥運算符
- ⑦結構語句
- 1、分支結構(選擇語句)
- 2、循環結構
- 退出循環
- break語句
- continue語句
- goto語句
- ⑧函數
- 函數的定義和調用
- 參數
- 函數的返回值
- 遞歸函數
- 零起點學通C語言摘要
- 內部函數和外部函數
- 變量存儲類別
- ⑨數組
- 指針
- 結構體
- 聯合體(共用體)
- 預處理器
- 預處理器的工作原理
- 預處理指令
- 宏定義
- 簡單的宏
- 帶參數的宏
- 預定義宏
- 文件包含
- 條件編譯
- 內存中的數據
- C語言讀文件和寫文件
- JNI知識點總結
- 前情回顧
- JNI規范
- jni開發
- jni開發中常見的錯誤
- JNI實戰演練
- C++(CPP)在Android開發中的應用
- 掘金網友總結的音視頻開發知識
- 音視頻學習一、C 語言入門
- 1.程序結構
- 2. 基本語法
- 3. 數據類型
- 4. 變量
- 5. 常量
- 6. 存儲類型關鍵字
- 7. 運算符
- 8. 判斷
- 9. 循環
- 10. 函數
- 11. 作用域規則
- 12. 數組
- 13. 枚舉
- 14. 指針
- 15. 函數指針與回調函數
- 16. 字符串
- 17. 結構體
- 18. 共用體
- 19. typedef
- 20. 輸入 & 輸出
- 21.文件讀寫
- 22. 預處理器
- 23.頭文件
- 24. 強制類型轉換
- 25. 錯誤處理
- 26. 遞歸
- 27. 可變參數
- 28. 內存管理
- 29. 命令行參數
- 總結
- 音視頻學習二 、C++ 語言入門
- 1. 基本語法
- 2. C++ 關鍵字
- 3. 數據類型
- 4. 變量類型
- 5. 變量作用域
- 6. 常量
- 7. 修飾符類型
- 8. 存儲類
- 9. 運算符
- 10. 循環
- 11. 判斷
- 12. 函數
- 13. 數學運算
- 14. 數組
- 15. 字符串
- 16. 指針
- 17. 引用
- 18. 日期 & 時間
- 19. 輸入輸出
- 20. 數據結構
- 21. 類 & 對象
- 22. 繼承
- 23. 重載運算符和重載函數
- 24. 多態
- 25. 數據封裝
- 26. 接口(抽象類)
- 27. 文件和流
- 28. 異常處理
- 29. 動態內存
- 30. 命名空間
- 31. 預處理器
- 32. 多線程
- 總結
- 音視頻學習 (三) JNI 從入門到掌握
- 音視頻學習 (四) 交叉編譯動態庫、靜態庫的入門學習
- 音視頻學習 (五) Shell 腳本入門
- 音視頻學習 (六) 一鍵編譯 32/64 位 FFmpeg 4.2.2
- 音視頻學習 (七) 掌握音頻基礎知識并使用 AudioTrack、OpenSL ES 渲染 PCM 數據
- 音視頻學習 (八) 掌握視頻基礎知識并使用 OpenGL ES 2.0 渲染 YUV 數據
- 音視頻學習 (九) 從 0 ~ 1 開發一款 Android 端播放器(支持多協議網絡拉流/本地文件)
- 音視頻學習 (十) 基于 Nginx 搭建(rtmp、http)直播服務器
- 音視頻學習 (十一) Android 端實現 rtmp 推流
- 音視頻學習 (十二) 基于 FFmpeg + OpenSLES 實現音頻萬能播放器
- 音視頻學習 (十三) Android 中通過 FFmpeg 命令對音視頻編輯處理(已開源)