Featured image of post Linux02-Shell脚本

Linux02-Shell脚本

Shell脚本的创建与执行

创建脚本文件*.sh

使用touch命令新建test.sh文件。这里.sh的后缀名并不是必须的,任何后缀名甚至是无后缀名都可以。

1
touch test.sh
引入shell声明序列

shell脚本需要符合首行she-bang机制,在第一行使用#!引入shell声明序列。这里#!/bin/bash是指该脚本默认用bash解释器执行。

1
#!/bin/bash

同理,如果想用python执行脚本,则可以在首行引入:

1
#!/bin/python3
为脚本赋予执行权限并执行

新建的脚本无执行权限,需要使用chmod a+x命令赋予其执行权限。之后使用./test.sh即可执行脚本。如果将脚本位置加入环境变量,则可以直接输入脚本名称运行而不再需要前面的./

1
2
chmod a+x test.sh
./test.sh

shell变量

定义变量

变量是用于存储数据值的名称。使用变量名=变量值即可给变量赋值。其注意点包括:

  • 等号两边不能有空格

  • 定义变量时,变量名前不能加美元符号$

  • 变量值可以不加引号,但是如果中间有空格或特殊符号,则应当用引号包裹

  • 使用双引号可以在引号内使用变量展开或转义符号,而单引号则会严格保留原始字符

1
2
3
PI=3.14
NAME=Xiaoming
NAME="Xiao ming"
使用变量

想要使用一个变量,则直接在前加上美元符号$即可。

  • 变量名外面的花括号可加可不加,如果不加则会匹配$后所有字符,直到出现不可用在变量里的字符为止。加上花括号可以界定变量名的边界,在实际使用中建议都加上花括号。
1
2
3
4
5
NAME="Xiao ming"
echo Hello,$NAME		# 输出 Hello,Xiao ming
echo "Hello,$NAME"		# 输出 Hello,Xiao ming
echo "Hello,${NAME}"	# 输出 Hello,Xiao ming
echo 'Hello,$NAME'		# 输出 Hello,$NAME
变量类型

shell中最常见的变量就是字符串和数字,并且以字符串使用最多。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 字符串,字符串可以不用引号,也可以用单引号和双引号。其中单引号没法使用变量展开或转义符号
NAME=XiaoMing

# 整数,需要使用declare命令
declare -i my_integer=42

# 数组
my_array=(1 2 3 4 5)
echo ${my_array[0]}
echo $((${my_array[0]}+${my_array[1]}))		#$((expr))可以进行数学运算。这里会输出3。

此外,shell中还存在一些特殊的变量:

$PATH:环境变量,包含了操作系统搜索可执行文件的路径。

$0 表示脚本的名称

$1$2,…… :表示传递给脚本的第几个参数。

$#:表示传递给脚本的参数数量

$?:表示上一个命令的退出状态等。

Shell参数传递

在执行 Shell 脚本时,可以向脚本传递参数,脚本内获取参数的格式为$n,其中n代表一个数字,1为执行脚本的第一个参数,2为执行脚本的第二个参数。

1
2
3
4
5
#!/bin/bash
echo "第一个参数为$1"
echo "第二个参数为$2"
echo "参数的个数为$#"
echo "将所有的参数作为一个字符串显示:$*"

然后运行该脚本:

1
./test.sh ABC 123

输出内容如下:

1
2
3
4
第一个参数为ABC
第二个参数为123
参数的个数为2
将所有的参数作为一个字符串显示:ABC 123

Shell运算符

算数运算符

bash不支持直接的数学运算,但是可以使用expr命令,或$((...))来实现。使用expr命令时需要用反引号将expr和表达式包裹起来,同时使用乘法符号时要用反斜杠进行转义。

常见的算数运算符如下:

 1
 2
 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
a=1
b=2
# 加
echo $(($a + $b))
echo `expr $a + $b`

# 减
echo $(($a - $b))
echo `expr $a - $b`

# 乘
echo $(($a * $b))
echo `expr $a \* $b`	# 需要加转义符号

# 除
echo $(($a / $b))
echo `expr $a / $b`

# 取余
echo $(($a % $b))
echo `expr $a % $b`

# 赋值
a=$b

# 判断是否相等
echo $(($a == $b))
echo `expr $a == $b`

# 判断是否不相等
echo $(($a != $b))
echo `expr $a != $b`
关系运算符

进行数值比较时,可以使用旧式的 [ expression1 OP expression2 ],OP可以为 “小于”-gt、“大于”-lt、“大于等于”-ge、“小于等于”-le、“相等”-eq、“不相等”-ne ,也可以使用新式的 ((expression1 OP expression2)),OP可以为 ><>=<===!=。新式的写法格式更加自然,同时支持更多高级功能。

布尔运算符

常用的布尔运算符包括:“非”!、“或”-o、“与”-a

字符串运算符

常用的字符串运算符包括:

=:检测两个字符串是否相等

!=:检测两个字符串是否不相等

-z:检测字符串长度是否为0

-n:检测字符串长度是否不为0

$:检测字符串是否不为空

文件测试运算符

最常用的式-e,检测文件是否存在

Shell的流程控制

条件判断 if … fi

if-elif-else语法格式:

1
2
3
4
5
6
7
if [ condition ]; then
	command
elif [ condition ]; then
	command
else
	command
fi

其中:

  • 任何一个分支都不能为空。如果该分支没有要执行的内容,就不要写这个分支。
  • condition与左右方括号之间都必须有一个空格。
  • 在单方括号内大于或小于等关系运算符要用-gt-lt等,不能使用符号。
  • 如果使用双括号((…)),则既不用两边空格,也可以直接使用符号。
  • 不管使用那种括号,关系运算符两边都必须有一个空格。
1
2
3
4
5
6
7
8
age=50
if [ $age -lt 20 ]; then
	echo "young"
elif [ $age -lt 60 ]; then
	echo "adult"
else
	echo "elderly"
fi
多选择语句 case … esac

case … esac 的基本语法格式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
case $Var in
pattern1)
    command1
    command2
    ...
    commandN
    ;;
pattern2)
    command1
    command2
    ...
    commandN
    ;;
esac

case工作方式如上所示,取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至;;

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号*捕获该值,再执行后面的命令。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
NAME=Xiaoming
case "$NAME" in
	"Xiaohong") echo "Welcome_$NAME"
	;;
	"Xiaogang") echo "Welcome_$NAME"
	;;
	"Xiaozhao") echo "Welcome_$NAME"
	;;
	*) echo "You are not on the namelist"
	;;
esac
for循环

for循环的基本语法如下:

1
2
3
4
5
6
for var in item1 item2 ... itemN; do
	command1
	command2
	...
	commandN
done

此外,continue可以跳过这一次循环,break可以跳过所有循环。

一个for循环的例子如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 输出1-1000内的所有素数到prime.txt中
for i in $(seq 1 1000); do
	if [ $i -eq 2 ]; then
		echo "$i " >> prime.txt
	else
		for j in $(seq 2 $(($i-1))); do
			if [ $(($i % $j)) -ne 0 ]; then
				if [ $j -eq $(($i-1)) ]; then
					echo $i >> prime.txt
				fi
			else
				break
			fi
		done
	fi
done
while和until循环

while 循环用于不断执行一系列命令,也用于从输入文件中读取数据。其语法格式为:

1
2
3
while condition; do
	command
done

在while循环中,只要condition为true就会一直循环。而until 循环正好相反,当condition为false时会一直循环:

1
2
3
until condition; do
	command
done

一个典型例子如下:

1
2
3
4
5
6
7
8
# 计算给定数的阶乘
sum=1
i=1
while [ $i -le $1 ]; do
	sum=$(($sum*$i))
	i=$(($i+1))
done
echo $sum

Shell函数

定义函数

shell中函数的定义格式如下:

1
2
3
4
function_name(){
    action
    return int
}
  • return语句只能返回一个介于 0 到 255 之间的整数,而两个输入数字的和可能超过这个范围。要解决这个问题,可以直接使用echo输出而不是使用return
  • 在Shell中,调用函数时可以向其传递参数。在函数体内部,通过$n的形式来获取参数的值。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 计算给定数的阶乘
Fac(){
	if [ $1 -gt 25 ]; then
		echo "Too Large"
		return 0
	fi
	sum=1
	i=1
	while [ $i -le $1 ]; do
		sum=$(($sum*$i))
		i=$(($i+1))
	done
	echo $sum
	return 1
}
使用函数

直接使用函数名+参数即可:

1
Fac 20
welcome to my blog
使用 Hugo 构建
主题 StackJimmy 设计