---
# System prepended metadata

title: 第四堂課，因為有人要我上apcs所以繼續來說linux

---

# 第四堂課，因為有人要我上apcs所以繼續來說linux

上次下課之後我朋友Jason過來跟我說他覺得我的課太廢了，希望我能改上程式語言。而實際上我看了自己上個禮拜上的東西後也覺得有點廢，所以今天就讓我們來上更加進階、有趣的bash和shell script吧！

## Bash是什麼
全名為Bourne-Again SHell，Bash是一個命令處理器，通常執行於文字窗口中，並能執行使用者直接輸入的命令。Bash還能從檔案中讀取命令，這樣的檔案稱為指令碼。
在第一堂課我們說過「Linux內核是整個作業系統的核心，負責管理軟體發出的資料I/O（輸入與輸出）。它會作為電腦上硬體與軟體的橋樑」那麼要如何與內核溝通呢？就必須要透過Shell了！
shell這個英文字比起想像它是一個殼層，想像它是馬力歐賽車里的烏龜殼可能還更適合。shell裡面裝著我們所打的指令，就這樣滾進又滾出內核，差不多就是這樣。
## shell script呢？
而shell script就是由一堆bash指令加上一些判斷試與迴圈的執行檔，但也可以當作是一個小程式了

比如說我寫了個virc.sh:

```
[john@ethernet Desktop]$ sh virc.sh #在子程序中打開virc.sh
parameters are: 

        --hello
                prints Hello World! 

        --test 
                prints test message. 

        --kbomb 
                runs the kbomb apcs program. 

        --help 
                prints this message. 

[john@ethernet Desktop]$ sh virc.sh --hello #使用hello選項
Hello World! 

[john@ethernet Desktop]$ sh virc.sh --kbomb
Please input 'N M K':5 2 4   #輸入5 2 4
3
```
可以作到這樣呢

## 先學基礎的變數吧：

1.用echo印出變數：
```
echo ${變數}
#example
[john@ethernet Desktop]$ echo ${RANDOM} #0到32767的整數
12354
```
2.查看系統變數：（都是大寫）env:環境變數，set:環境加自訂變數
```
[john@ethernet Desktop]$ env
XDG_SESSION_DESKTOP=KDE
LOGNAME=john
XDG_SESSION_TYPE=x11
XAUTHORITY=/home/john/.Xauthority
MOTD_SHOWN=pam
GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/john/.gtkrc-2.0:/home/john/.config/gtkrc-2.0
HOME=/home/john
LANG=zh_TW.UTF-8
XDG_CURRENT_DESKTOP=KDE
......
```
3.設定變數基礎：
```
[john@ethernet Desktop]$ virc=cool 
[john@ethernet Desktop]$ echo ${virc}
cool
[john@ethernet Desktop]$ 1virc=cool #開頭不能為數字
bash: 1virc=cool：指令找不到
[john@ethernet Desktop]$ virc = cool #等號兩邊不能直接接空白字元
bash: virc：指令找不到
[john@ethernet Desktop]$ export virc #將virc導出為環境變數
```

4.設定變數進階：

一，變數中的指令
```
echo $(指令輸出結果)
[john@ethernet Desktop]$ echo $(uname -r) #linux內核版本
5.4.113-1-lts54
＃變數＝＄（指令）的結果
[john@ethernet Desktop]$ myname=$(uname -r)
[john@ethernet Desktop]$ echo ${myname}
5.4.113-1-lts54
#當然還可以更活用比如：
[john@ethernet Desktop]$ cd /lib/modules/$(uname -r)/kernel ＃進入到目前內核的模組目錄
[john@ethernet kernel]$ 
```
二，變數中的變數
```
[john@ethernet Desktop]$ echo ${virc}
cool
[john@ethernet Desktop]$ virc=${virc}verycool
[john@ethernet Desktop]$ echo ${virc}
coolverycool
```
5.萬用字元
\*    
代表『 0 個到無窮多個』任意字元
?	
代表『一定有一個』任意字元
[ ]	
同樣代表『一定有一個在括號內』的字元(非任意字元)。例如 [abcd] 代表『一定有一個字元，可能是 a, b, c, d 這四個任何一個』
[ - ]	
若有減號在中括號內時，代表『在編碼順序內的所有字元』。例如 [0-9] 代表 0 到 9 之間的所有數字，因為數字的語系編碼是連續的！
[^ ]	
若中括號內的第一個字元為指數符號 (^) ，那表示『反向選擇』，例如 [^abc] 代表 一定有一個字元，只要是非 a, b, c 的其他字元就接受的意思。

6.特殊符號：
\\
跳脫符號：將『特殊字元或萬用字元』還原成一般字元
|
管線 (pipe)：分隔兩個管線命令的界定(之後講)；
;
連續指令下達分隔符號：連續性命令的界定 (注意！與管線命令並不相同)
~
使用者的家目錄

7.簡單運算
```
declare [-aixr] variable
選項與參數：
-a  ：將後面名為 variable 的變數定義成為陣列 (array) 類型
-i  ：將後面名為 variable 的變數定義成為整數數字 (integer) 類型
-x  ：用法與 export 一樣，就是將後面的 variable 變成環境變數；
-r  ：將變數設定成為 readonly 類型，該變數不可被更改內容，也不能 unset
[john@ethernet Desktop]$ declare -i number=50
[john@ethernet Desktop]$ number=$((${number}+100))
[john@ethernet Desktop]$ echo ${number}
150
```
\+  -  *  /  %
## 判斷式與迴圈:

8.if判斷式
```
if [ 條件判斷式一 ]; then
	當條件判斷式一成立時，可以進行的指令工作內容；
elif [ 條件判斷式二 ]; then
	當條件判斷式二成立時，可以進行的指令工作內容；
else
	當條件判斷式一與二均不成立時，可以進行的指令工作內容；
fi
```

9. case ..... esac 判斷式
```
case  $變數名稱 in   <==關鍵字為 case ，還有變數前有錢字號
  "第一個變數內容")   <==每個變數內容建議用雙引號括起來，關鍵字則為小括號 )
	程式段
	;;            <==每個類別結尾使用兩個連續的分號來處理！
  "第二個變數內容")
	程式段
	;;
  *)                  <==最後一個變數內容都會用 * 來代表所有其他值
	不包含第一個變數內容與第二個變數內容的其他程式執行段
	exit 1
	;;
esac                  <==最終的 case 結尾！

```
10.while do done, until do done 迴圈
```
while [ condition ]  <==中括號內的狀態就是判斷式
do            <==do 是迴圈的開始！
	程式段落
done          <==done 是迴圈的結束

```
```
until [ condition ]
do
	程式段落
done
```
11.for...do...done 迴圈
```
for var in con1 con2 con3 ...
do
	程式段
done
#example
[john@ethernet Desktop]$ for apcs in c++ python c java
do
	echo "There are ${apcs} in apcs"
done
There are c++ in apcs
There are python in apcs
There are c in apcs
There are java in apcs
#or
[john@ethernet Desktop]$ for apcs in c++ python c java; do  echo "There are ${apcs} in apcs"; done
There are c++ in apcs
There are python in apcs
There are c in apcs
There are java in apcs
#or
[john@ethernet Desktop]$ declare -i apcs=0
[john@ethernet Desktop]$ for apcs in $(seq 1 100) ; do    apcs=$(($apcs+1)) ; done #（seq 1 100為1到100）
[john@ethernet Desktop]$ echo ${apcs}
101
```
12.for...do...done 迴圈
```
for (( 初始值; 限制值; 執行步階 ))
do
	程式段
done
#初始值：某個變數在迴圈當中的起始值，直接以類似 i=1 設定好；
#限制值：當變數的值在這個限制值的範圍內，就繼續進行迴圈。例如 i<=100；
#執行步階：每作一次迴圈時，變數的變化量。例如 i=i+1,i++
#example
[john@ethernet Desktop]$ s=0
[john@ethernet Desktop]$ nu=10
[john@ethernet Desktop]$ for (( i=1; i<=${nu}; i=i+1 ))
do
	s=$((${s}+${i}))
done
[john@ethernet Desktop]$ echo ${s}
55
```

## 參考資料與延伸學習

[http://linux.vbird.org/linux_basic/0320bash.php](http://linux.vbird.org/linux_basic/0320bash.php)

[http://linux.vbird.org/linux_basic/0340bashshell-scripts.php](http://linux.vbird.org/linux_basic/0340bashshell-scripts.php)