技术交流QQ群:1027579432,欢迎你的加入!
本教程使用Linux发行版Centos7.0系统,请您注意~
1.使用多个命令
shell脚本的关键之处在于输入多个命令并处理每个命令的结果,甚至需要将一个命令的结果传给另一个命令。shell可以让多个命令串起来,一次执行。如果要两个命令一起运行,可以将它们放在同一行,之间用逗号隔开。
1
2
3
4[njust@njust tutorials]$ date;who
2020年 03月 11日 星期三 22:39:16 CST
njust :0 2020-03-11 22:28 (:0)
njust pts/0 2020-03-11 22:35 (192.168.0.107)上述方法的缺点:使用上述方法可以将任意多个命令串联在一起使用,最大命令行字符数不超过255个。对小型的脚本适用,当有很多脚本时,直接在命令行中输入整个命令就很麻烦。
2.创建shell脚本文件
创建shell脚本文件时,必须在文件的第一行指定使用的shell是哪种类型,格式为:
1
shell脚本中注释一般以#开头,shell脚本不会处理注释的行。但是,shell脚本的第一行是例外。#后的!会告诉shell用哪个shell来运行脚本,shell会根据命令在文件中出现的先后顺序进行处理。下面是创建脚本名为demo的文件。
1
2
3
date
who存在的问题:如何让bash shell找到你创建的脚本文件?shell会通过PATH环境变量来查找命令。PATH环境变量被设置成只在一组目录中查找命令。
1
2[njust tutorials]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/njust/.local/bin:/home/njust/bin解决方法:让shell找到脚本文件,有两个方法:
- 将shell脚本文件所处的目录添加到PATH环境变量中;
- 在命令行中使用绝对或相对的路径来引用shell脚本文件(常用);
由于你还没有执行文件的权限,这是由于umask变量被设置为022,因此系统创建的文件只有读写权限。使用下面的命令赋予文件有可执行权限。
1
chmod u+x demo
为了引用当前目录下的文件,可以在shell中使用单点操作符.。正式执行脚本demo
1
./demo
3.显示消息
在echo命令后加上一个字符串,该命令就会显示出这个文本字符串。默认情况下,不需要使用引号将需要显示的字符串包含起来。
1
2[njust@njust tutorials]$ echo hello world
hello world当字符串中含有单引号或双引号时,可以使用双引号或单引号(注意叙述的顺序)包含该字符串。
1
2[njust"Let's see if this'll work" tutorials]$ echo
Let's see if this'll workecho命令可以添加到shell脚本中任何需要显示额外信息的地方!
- 当需要把字符串和命令输出显示在同一行时,可以使用带参数n的echo命令,如下所示:
1
2
3
4
5
6
7
echo -n "The time and date are: "
date
# 结果
The time and date are: 2020年 03月 11日 星期三 23:07:03 CST
4.使用变量
- 变量可以将临时信息存储在shell脚本中,便于和shell中其他的命令一起使用。
- 环境变量:shell维护一组环境变量,用来记录特定的系统信息。可以使用set命令来显示一份完整的当前环境变量列表。
在脚本中,可以在环境变量名称前加上美元符号$从而来使用这些变量。
1
2
3
4
5
6
7
8
9
10
11
12
# print information about logger
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME
# 结果
User info for userid: njust
UID: 1000
HOME: /home/njust注意:echo命令中的环境变量会在脚本运行时替换成当前值,只要脚本在引号中出现美元符,它就会以为你在引用一个变量,因此在表示真实美元的含义时,需要在$符号前加\转义字符。
1
2
3
echo "The cost of the item is \$5."此外,还可以通过${变量名}的形式引用变量,变量名两侧的{}通常用于帮助识别美元符后的变量名。
- 用户变量:除了环境变量外,shell还允许在脚本中定义和使用自己的变量。变量名使用字母、数字或下划线组成的字符串表示,长度最长不超过20个。
注意:使用等号将值赋给用户自定义的变量,在变量、等号和值之间不能出现空格!!!
1
2
3
4var1=23 # 等号左右不能出现空格!!
var2=demo
var3=testing
var4="hello shell"shell脚本会自动决定变量值的数据类型。在脚本的整个生命周期内,shell脚本定义的变量会一直存在,在shell脚本结束时会被删除。用户变量也可以通过$引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
days=10
guest="curry"
echo "$guest checked in $days days ago"
days=5
guest="durant"
echo "$guest cheked in $days days ago"
# 结果
curry checked in 10 days ago
durant cheked in 5 days ago变量每次引用时,都会输出当前赋给它的值。引用一个变量时需要使用美元符号$,引用一个变量var1给另一个变量var2进行赋值时,被赋值的变量不要使用$。对var1忘记使用$号,就会使var2的赋值行变成普通的字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var1=10
var2=$var1 # 在赋值语句中使用var1变量的值时,必须使用$符号
echo The resulting value is $var2
# 结果
The resulting value is 10
var2=var1; # 错误的代表案例,输出结果是普通字符串
echo The resulting value is $var2
# 错误结果
The resulting value is var1命令替换:shell最有用的特性之一是从命令输出中提取出信息,并将其赋值给变量。将命令的输出赋值给变量后,就可以在脚本中使用了。有两种方法可以将命令输出赋值给变量:
- 反引号字符`
- $()格式
命令替换允许你将shell命令的输出赋值给变量,具体如下所示:
1
2
3
4
5
6
7
8
9
10#!/bin/bash
testing=`date`
test=$(date)
echo The date and time are: $testing
echo The date and time are: $test
# 结果
The date and time are: 2020年 03月 12日 星期四 09:11:38 CST
The date and time are: 2020年 03月 12日 星期四 09:11:38 CST实例:通过命令替换获得当前日期并用它来生成唯一的文件名。
1
2
3
4
5
6
7
8
9
# copy the /usr/bin/directory listing to a log file
today=$(date +%y%m%d) # +%y%m%d格式是告诉date命令将日期显示为两位数的年月日数字组合
ls /usr/bin -al > log.$today
# 结果
生成log.200312日志文件命令替换会创建一个子shell来运行对应的命令,由该子shell所执行命令是无法使用脚本中所创建的变量。在命令行中使用路径./运行命令时,也会创建子shell;在运行命令时不加入路径,就不会创建子shell。
5.重定向输入和输出
- 重定向目的:想要保存某个命令的输出而不仅仅是让结果输出在屏幕上。
输出重定向:最基本的重定向是将命令的输出发送在一个文件中。格式如下:
1
具体命令 > 输出文件名
实例如下:
1
2
3[njust@njust tutorials]$ date > test6
[njust@njust tutorials]$ cat test6
2020年 03月 12日 星期四 09:40:09 CST如果输出文件已经存在,重定向操作符会用新的文件数据覆盖已有文件。
1
2
3
4
5[njust@njust tutorials]$ who > test6
[njust@njust tutorials]$ cat test6
njust :0 2020-03-11 22:28 (:0)
njust pts/0 2020-03-12 08:39 (192.168.0.107)
njust pts/1 2020-03-12 08:41 (:0)有时候,你并不想覆盖原始文件中的内容,而是想将命令的输出追加到已有文件中。这种情况下,可以用>>来追加数据。
1
2
3
4
5
6[njust@njust tutorials]$ date test6
[njust@njust tutorials]$ cat test6
njust :0 2020-03-11 22:28 (:0)
njust pts/0 2020-03-12 08:39 (192.168.0.107)
njust pts/1 2020-03-12 08:41 (:0)
2020年 03月 12日 星期四 09:43:41 CST输入重定向:输入重定向将文件的内容重定向到命令,而不是将命令输出重定向到文件。输入重定向的格式:
1
具体命令 < 输入文件
具体实例:wc命令可以统计文件中的数据,默认情况下会输出3个值。
1
2[njust@njust tutorials]$ wc < test6
4 21 186 # 从左到右分别表示文本的行数、文本的词数、文本的字节数内联输入重定向:<<无需使用文件进行重定向,只需要在命令行中指定输入重定向的数据即可。注意:必须指定一个文本标记来划分输入数据的起始和结尾。任何字符串都可以作为文本标记,但数据的起始和结尾文本标记必须一致。格式:
1
2
3具体命令 EOF
data
EOF在命令行中使用内联输入重定向时,shell会用PS2变量中定义的次提示符来提示用户输入数据。
1
2
3
4
5
6[njust@njust tutorials]$ wc << EOF
> test string 1 # >表示的就是次提示符
> test string 2
> test string 3
> EOF
3 9 42
6.管道
- 管道的目的:一个命令的输出作为另一个命令的输入。
管道被放在命令之间,将一个命令的输出重定向到另一个命令中。基本格式如下:
1
命令1 | 命令2
管道串器的两个命令不是依次执行的,Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送个第二个命令。数据传输不会用的任何中间文件或缓冲区。
可以在一条命令中使用任意多条管道。可以持续地将命令的输出通过管道传给其他命令来细化操作。如下例所示:
1
2
3
4rpm -qa | sort | more # 先生成已安装包的列表,再排序,最后再用more显示
# 如果想更精致点,可以搭配使用重定向和管道将输出保存到文件中
rpm -qa | sort > rpm.list管道最流行的用法之一就是将产生的大量输出通过管道传给more命令,一般与ls命令结合使用。
7.执行数学运算
- 在shell中有两个途径进行数学运算。
- expr命令
- 使用方括号
expr命令允许在命令行中处理数学表达式,但特别笨拙。许多expr命令操作符在shell中另有含义,当它们出现在expr命令中时,会得到一些诡异的结果。对那些容易被shell错误解释的字符,需要使用转义字符。
1
2
3
4[njust@njust tutorials]$ expr 5 * 2
expr: 语法错误
[njust@njust tutorials]$ expr 5 \* 2
10在shell脚本中expr命令也同样复杂,如下所示:
1
2
3
4
5
6
7
8
9
var1=10
var2=20
var3=$(expr $var2 / $var1) # 要将一个数学表达式的结果赋值给一个变量var3,也需要借助命令替换。
echo The result is $var3
# 结果
The result is 2在bash中,在将一个数学运算结果赋给一个变量时,可以使用美元符和[]将整个表达式圈起来。
1
2
3[njust@njust tutorials]$ var1=$[1+34]
[njust@njust tutorials]$ echo $var1
35用方括号执行shell运算比用expr命令方便很多,在shell脚本中也能看出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#!/bin/bash
var1=10
var2=20
var3=`expr $var2 / $var1`
echo the result is $var3
var1=100
var2=200
var3=45
var4=$[$var1 * ($var3 - $var2)]
echo final result is $var4
# 结果
the result is 2
final result is -15500bash shell数学运算符只支持整数运算,这是一个巨大的限制。
1
2
3
4
5
6
7
8
9
var1=100
var2=45
var3=$[$var1 / $var2]
echo The final result is $var3
# 结果
The final result is 2浮点数运算的解决方案:使用内建的bash计算器bc。bash计算器允许在命令行中输入浮点表达式,然后解释并计算该表达式,返回结果。
浮动运算是由内建变量scale控制的,这个值设置为你需要保留的小数点后几位。
1
2
3
4
5
6
7[njust@njust ~]$ bc -q # -q参数表示不显示欢迎信息
3.44 /5
0
scale=4
3.44 / 5
.6880
quitbash计算器还支持变量,如下所示:
1
2
3
4
5
6
7
8bc -q
var1=10
var1*4
40
var2=var1 / 5
print var2
2
quit在脚本中使用bc:可以使用命令替换运行bc命令,并将输出赋值给一个变量,基本格式如下:
1
变量名=$(echo "可选项; 表达式" | bc)
实例:在脚本中使用bc,如下所示。
1
2
3
4
5
var1=$(echo "scale=4; 3.44/5" | bc)
echo $var1
.6880上述方法适用于较短的运算,但有时候涉及更多的数字。需要进行大量的运算,在一个命令行中列出多个表达式就会麻烦。解决方法:使用内联输入重定向,它允许你直接在命令行中重定向数据。基本格式为:
1
2
3
4
5变量名=$(bc << EOF
可选项
语句
表达式
EOF)在bash计算器中创建的变量只在bash计算器中有效,不能在shell脚本中使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#!/bin/bash
var1=10.46
var2=43.67
var3=33.2
var4=71
var5=$(bc << EOF
scale=4
a1 = ($var1 * $var2)
b1 = ($var3 * $var4)
a1 + b1
EOF
)
echo final result is $var5
# 结果
final result is 2813.9882
8.退出脚本
shell中运行的每个命令都使用退出状态码,shell告诉它已经运行完毕。退出状态码是一个0到255的整数值,在命令结束时由命令传给shell,可以捕捉这个值在脚本中使用。Linux专门提供了变量$?来保存上一个已执行命令的退出状态码。对于需要进行检查的命令,必须在其运行完毕后立即查看或使用$?变量。
1
2
3
4[njust@njust tutorials]$ date
2020年 03月 12日 星期四 10:39:19 CST
[njust@njust tutorials]$ echo $?
0Linux退出状态码如下:
1
2
3
4
5
6
70 命令成功结束
1 一般性未知错误
2 不适合的shell命令
126 命令不可执行
127 没找到命令
128 无效的退出参数
130 通过CTRL+C终止的命令exit命令:默认情况下,shell脚本会以脚本中最后一个命令的退出状态码退出。用户可以改变这种默认行为,返回自己的状态码。eixt命令允许在脚本结束时指定一个退出状态码。
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#!/bin/bash
var1=10
var2=30
var3=$[$var1 + $var2]
echo The answer is $var3
exit 5
# 结果
The answer is 40
echo $?
5
# 也可以在exit命令的参数中使用变量
exit $var3
echo $?
40
# 注意:退出状态码最大为255,超过最大的255后,会通过取模运算得到最后的结果即实际值 % 256 = 最结果
var1=10
var2=30
var3=$[$var1 * $var2]
echo The answer is $var3
exit $var3
echo $?
44