第19章 会编程的bash(上)
bash是一个命令解释器。在前面章节中介绍了在bash中输入命令,它会把输入的命令转化为特定的动作。本章将介绍bash的可编程性。
一、变量
在C语言中,变量是内存中的一块空间,可以用于存储数据。我们可以通过变量名来引用变量中保存的数据。bash和C语言类似,也有变量,但bash中的变量只能存储文本。
1、使用赋值符号"="来表示赋值,比如:
$var=World
赋值就是把文本World存入名为var的变量。根据bash的语法,赋值符号前后不能加空格
如果文本中包含空格,可以使用单/双引号来包裹文本。
用户也可以直接向bash输入数据,这要用到read命令,该命令运行后,bash等待用户输入,比如:
$read name
命令read后跟着name,说明了等待存储数据的变量名。此时输入字符串然后回车,就会给name赋值。
2、引用变量
我们可以用$var的方式来引用变量。
为了避免变量名和尾随的普通文本混淆,我们也可以用${var}的方式来表示变量。
在bash中,为了把一段包含空格的文本当作单一参数,需要用到单/双引号。而双引号中可以使用变量,单引号则会被忽视,如:
$echo "Hello $var"
可以正常引用变量。
而下面则会直接打印出Hello $var
$echo 'Hello $var'
二、数学运算
在bash中,由于数字和运算符都被当做普通文本,因此无法像C语言那样便捷地进行数学运算。如以下赋值并不会进行任何运算,而是把文本直接赋值。
$result=1+2
在bash中可以用$(())语法来进行数值运算。双括号中可以放入证书的加减乘除表达式。如:
$echo $((2 + (5*2)))
也可以引用变量,如:
$echo $(($var + (5*2)))
乘方的运算符为**,如:
$echo $((2 + 5*2**(5-3)/2))
算术优先级和数学上一致,毋庸赘述。
三、返回代码
在Linux中,每个可执行程序会有一个整数的返回代码。按照Linux惯例,程序正常运行完毕并返回时,将返回整数0。在shell中,运行程序后,可以通过$?变量来获知返回码,比如:
$./a.out
$echo $?
如果程序运行异常,则这个程序返回一个非0的返回代码,比如删除一个不存在的文件。
在Linux中可以在一行命令中执行多个程序,我们可以让后一个程序的运行参考前一个程序的返回代码。比如只有前一个程序返回成功代码0时,才让后一个程序运行:
$rm demo.file && echo "rm succeed"
还有一种情况是等前一个程序失败了,才运行后一个程序,比如:
$rm demo.file || echo "rm fail"
四、bash脚本
1.脚本的例子
多行的bash命令写入一个文件就形成了所谓的bash脚本。
脚本的第一行说明该脚本使用的Shell:
#!/bin/bash
在bash脚本种,可以在句首用“#”符号来表示该行是注释。
2.脚本参数
bash脚本在运行时,也可以携带参数。可以$0,$1,$2……的方式来获得bash脚本运行的参数。例如:
$./test_arg.bash hell world
$0是命令的第一部分,也就是./test_arg.bash,$1和$2分别代表了参数hello和world。
3.脚本的返回代码
一个脚本如果正常运行完最后一句,会自动返回代码0。我们也可以用exit命令来设置脚本的返回代码。如exit 1
五、函数
在bash中我们可以蚕蛹函数的形式来实现脚本内部的部分程序复用。在定义函数时,我们需要用花括号来标识函数包括的部分:
#!/bin/bash
#定义函数 my_info
function my_info(){
#此处省略函数内容
}
#调用函数
my_info
其中函数定义的function关键字不是必须的。
在函数内部,通用可以用$1、$2这样形式的变量来调用参数。
六、跨脚本调用
使用source命令可以实现函数的跨脚本调用。类似于C源中的#Include关键字。
第20章 会编程的bash(下)
一、逻辑判断
在bash中我们可以用test命令来进行逻辑判断:
$test 3 -gt 2; echo $?
命令test后面跟着一个表达式,其中**-gt表示大于**,即greater than,3大于2表达式为真,所以返回代码为0,若表达式为假,则返回代码为1。
此外:
-lt表示小于,即less than;
-eq表示等于;
-nq表示不等于;
-ge表示大于等于;
-le表示小于等于。
bash中最常见的数据形式是文本,因此也提供了很多关于文本的判断:
文本相同:
$test abc = abx; echo $?
文本不同:
$test abc != abx; echo $?
按照字典顺序,一个文本在另一个文本之前:
$test apple > tea; echo $?
按照字典顺序,一个文本在另一个文本之后:
$test apple < tea; echo $?
bash还可以对文件状态进行判断:
检查一个文件是否存在:
$test -e a.out; echo $?
检查一个文件是否存在,而且是普通文件(-f)、目录文件(-d)、软链接(-L):
$test -f file.txt; echo $?
检查一个文件是否可读(-r)、可写(-w)、可执行(-x):
$test -r file.txt; echo $?
在做逻辑判断时,可以把多个逻辑判断条件用“与、或、非”组合起来,形成符合逻辑判断。
!expression(非)
expression1 -a expression2(与)
expression1 -o expression2(或)
二、选择结构
bash可以使用if结构,关键字if后面跟着[],里面是一个逻辑表达式。举例如下:
#!/bin/bash
filename = $1
if[ -e $filename]
then
echo "$filename exists"
else
echo "$filename Not exists"
fi
此外,还可以在内部嵌套选择结构,从而实现更多代码块的选择执行。
在bash中,还可以用case语法来实现多程序块的选择执行。比如:
#!/bin/bash
var = 'whoami'
echo "You are $var"
case $var in
root)
echo "You are God."
;;
vamei)
echo "You are a happy user."
;;
*)
echo "You are the others."
;;
esac
文本标签除了是一串具体的文本,还可以包含文本通配符。结构case常用的通配符如下:
* 任意文本
? 任意一个字符
[] 范围内的一个字符
三、循环结构
while语法举例,下面程序以无限循环的形式,不断播报时间:
#!/bin/bash
while true
do
date
sleep 1
done
for语法举例:
#!/bin/bash
for user in vamei anna yutian
do
echo $user
done
此外,for循环还可以和seq命令配合使用。命令seq用于生成一个等差的整数序列,命令后面跟三个参数,分别为序列起始数字,增加值,序列终点数字。
结合for循环和seq命令,我们可以解一些数学问题,比如高斯求和:
#!/bin/bash
total = 0
for number in 'seq 1 1 100'
do
total =$(( $total + $number ))
done
echo $total
四、bash和C语言
相似性:
都存在以下语法:变量、循环结构、选择结构、函数
bash和C的相似性来自于它们共同遵守的编程范式–面向过程编程。
区别:
bash的变量只能是文本类型,C的变量可以是整数、浮点数、字符等;
bash中的很多功能如加减乘除运算,都是通过调用其他程序实现的,而c直接就可以进行运算。
bash是一个Shell,它本质上是一个命令解释器程序,而不是编程语言。