昨天介绍了套件管理软件以及图形化使用者界面的安装,也是指令介绍的最後一篇文章。学习了这麽多指令後,如果能灵活运用,使用 Linux 来做一些基础的软件开发我想应该都还撑的住!
今天是机派X系列文章的第八天。
本篇将介绍 Bash 的变数操作、条件判断与流程控制。学习过这些东西後,就能用 Bash 将数条指令组合起来依序执行,变成有用的小程序。
本篇大纲:
也许你会疑惑,为什麽要学习这些,这些很明显都是在学程序啊,但是我的专案又不用 Bash 开发!为何要学这些?
原因很简单:如果以 Linux 做为开发平台,学习 Bash 有助於你写一些「小工具」,让你在主要程序开发的过程中更方便。
我会在下一篇文章中用 Bash 写一些实用的小程序,希望能解除大家的疑惑。
由於下一篇文章才会带领大家开新档案、撰写脚本,所以建议将本篇与下一篇搭配着看。
首先,来介绍变数这个东西。
可以想像变数(Variable)就是一个盒子,用於储存资料。撰写程序时,常常会需要很多不同的「盒子」来储存不同资料。每个变数(或说盒子)都有一个名称,该名称由写程序的人定义,以便撰写程序时调用,透过呼叫变数名称就可以取得或变更其中的资料内容。
在 Bash 中设定变数可以使用 export 来完成,若要取用变数则要透过 $ 。
以下是 export 的语法,并请注意 = 左右两边不可有空格!
export NAME[=DATA]
例如:
export my_name='Kevin Huang'
在变数名称前方加上 $ 就可以取得该变数的值:
echo "My name is $my_name !"
Note :
此时,单引号与双引号的使用就会出现差异。如果使用单引号,具有特殊意义的字元(例如:$ 符号)不会被解析,因此会「如实呈现」显示「My name is $my_name !」。如果使用双引号,具有特殊意义的字元(例如:$ 符号)才会被解析,因此会显示「My name is Kevin Huang !」。
接下来,你可以尝试以下范例:
export name='Kevin'
export name='$name Huang'
echo "$name"
export name='Kevin'
export name="$name Huang"
echo "$name"
Note :
如果你有学过其他程序语言,你可以能会好奇:怎麽没有介绍变数的资料型态(Data Type)呢?
Answer:因为 Bash 只有一种资料型态,就是字串(String),所以其实没有必要特别介绍,毕竟对於没有学过其他程序语言的新手来说,资料型态的概念比较陌生,Bash 这种特殊的资料型态不说也罢,说了之後搞不好概念更乱了。
可以使用 read 来读取使用者输入的资料,VARIABLE 则是储存使用者输入资料的变数名,-r 引数则是不解析输入资料中的跳脱字元,-p 引数则是给使用者的提示文字。
每次执行 read 都是读取一行,行中若有空白则会依照空白切割,并将切割出来的字串依序储存在变数中。
read [-r] [-p PROMPT] VARIABLE......
举例来说:
read -p 'Please input your name and address: ' name address
使用者输入:
Bella Taipei, Taiwan
可以使用 echo 印出使用者输入的文字:
echo "Hello $name. $address is a nice place."
有时候会需要针对资料内容做条件判断,依照判断的结果执行不同的指令。
举例来说:请使用者输入年龄,若输入的年龄大於等於 18 岁就 ...... ,否则就 ...... 。
以下是如果 TEST 条件判断为真(True),就会执行 Block 中的指令。
if [[ TEST ]]
then
# Block
fi
以下是如果 TEST 条件判断为真(True),就会执行 Block 1 中的指令;
如果条件判断为假(False),则会执行 Block 2 中的指令。
if [[ TEST ]]
then
# Block 1
else
# Block 2
fi
以下是如果 TEST1 条件判断为真(True),就会执行 Block 1 中的指令,其余测试则不再判断;如果条件判断为假(False),才会接续 TEST2 的判断。
如果 TEST2 条件判断为真(True),就会执行 Block 2 中的指令;如果条件判断为假(False),就会直接执行 Block 3 的指令。
if [[ TEST1 ]]
then
# Block 1
elif [[ TEST2 ]]
then
# Block 2
else
# Block 3
fi
Note :
TEST 是要执行的测试(test),依照测试结果会返回真(True)或假(False)。
测试 | 测试说明 |
---|---|
!TEST | 反转 TEST 的测试结果。 |
-z STRING | 判断 STRING 是否为空字串。 |
-n STRING | 判断 STRING 是否不为空字串。 |
STRING1 = STRING2 | 判断 STRING1 是否与 STRING2 相同。 |
STRING1 != STRING2 | 判断 STRING1 是否与 STRING2 不同。 |
STRING1 > STRING2 | 判断 STRING1 的 ASCII 序列是否大於 STRING2。 |
STRING1 < STRING2 | 判断 STRING1 的 ASCII 序列是否小於 STRING2。 |
INTEGER1 -eq INTEGER2 | 判断 INTEGER1 是否等於 INTEGER2。 |
INTEGER1 -ne INTEGER2 | 判断 INTEGER1 是否不等於 INTEGER2。 |
INTEGER1 -gt INTEGER2 | 判断 INTEGER1 是否大於 INTEGER2。 |
INTEGER1 -lt INTEGER2 | 判断 INTEGER1 是否小於 INTEGER2。 |
INTEGER1 -ge INTEGER2 | 判断 INTEGER1 是否大於或等於 INTEGER2。 |
INTEGER1 -le INTEGER2 | 判断 INTEGER1 是否小於或等於 INTEGER2。 |
TEST1 && TEST2 | 将 TEST1 与 TEST2 的测试结果做 AND 逻辑运算。 |
TEST1 || TEST2 | 将 TEST1 与 TEST2 的测试结果做 OR 逻辑运算。 |
-f PATH | 判断 PATH 是否存在,而且是一个档案。 |
-d PATH | 判断 PATH 是否存在,而且是一个目录。 |
-s PATH | 判断 PATH 是否存在,而且档案内容不为空。 |
-r PATH | 判断 PATH 是否存在,而且当前使用者对该档案具有读取权限。 |
-w PATH | 判断 PATH 是否存在,而且当前使用者对该档案具有写入权限。 |
-x PATH | 判断 PATH 是否存在,而且当前使用者对该档案具有执行权限。 |
举几个例子来看看吧:
read -p 'How old are you? ' age
if [[ $age -ge 18 ]]
then
echo 'Let us do something interesting ......'
fi
read -p 'How old are you? ' age
if [[ $age -ge 18 ]]
then
echo 'Let us do something interesting ......'
else
echo 'Go to the basement and sweep the floor!'
fi
read -p 'How many books on the shelf? ' numBook
if [[ $numBook -lt 0 ]]
then
echo '??????????????????????????????????'
elif [[ $numBook -eq 0 ]]
then
echo 'You can buy a book from www.books.com.tw .'
elif [[ $numBook -gt 10 ]]
then
echo 'You are a man or woman who likes to read!'
else
echo 'You can buy more books from www.books.com.tw .'
fi
有时候也会需要重复执行某些指令,因此会需要用到回圈(loop)。
回圈有很多种写法,以下将一一举例介绍。
for i in {0..10}
do
echo "There is/are $i rabbit(s)."
done
for i in {0..15..3}
do
echo "There is/are $i rabbit(s)."
done
for i in {1..9}
do
for j in {1..9}
do
printf " %1d * %1d = %2d" $i $j $(($i * $j))
done
echo ''
done
for i in {1..10}
do
for ((j=$i; j<=10; ++j))
do
echo -n '*'
done
echo ''
done
export TRUTH=(49 20 4C 4F 56 45 20 43 53 49 45)
for letter in ${TRUTH[@]}
do
printf "\x$letter"
done
echo ''
export name=''
while [[ -z $name ]]
do
read -p 'Your name? ' name
done
echo "Hello $name."
export number=2
while :
do
echo "There are $number dogs."
if [[ $number -eq 10 ]]
then
break
fi
export number=$(( $number + 1 ))
done
因为今天的文章内容有点乾,所以只好补张图化解尴尬气氛。
图源传送门
气氛现在从尴尬变成非常尴尬。
图源传送门
如果对於文章内容有建议、纠错或图源标示不正确的问题,欢迎参考 [机派X] Day 1 尝试与文章作者联络。
想看更多本系列的文章,请连结至 [机派X] Day 1 查看大纲。
Dos 攻击 全称为 Denial-of-Service Attack 即「阻断服务攻击」, 亦被称...
前言 我们在前面几章中介绍了this的绑定,说明了this最常被搞混的观点也介绍了如何透过call-...
适用人员: 技术人员。 适用法规: 资通安全责任等级分级办法 技术面分类提要 网路架构 端点安全防护...
控制反转与依赖注入一 ...
修复老照片 教学原文参考:修复老照片 这篇文章会介绍在 GIMP 使用「仿制工具」和「着色滤镜」,将...