2019独角兽企业重金招聘Python工程师标准>>>
10.1 使用多个命令
shell脚本的关键在于输入多个命令,并处理命令的结果,即使有可能将一个命令的结果传给另一个命令。
如果两个命令一起运行,可在同一提示行输入它们,用分号分隔开。
- 命令列表:在命令行中输入 date;who 命令
- 进程列表:在命令行中输入(date;who) 命令
[root@centos1 ~]# date ; who
Sat Dec 9 10:39:17 CST 2017
root pts/0 2017-12-09 10:01 (192.168.20.224)
10.2 创建shell脚本文件
要将shell命令放到一个文本文件中。在创建shell脚本文件时,必须在文件的第一行制动要使用的shell 其格式为:
#!/bin/bash
在通常的shell脚本里, 井号 # 用作注释行。 shell脚本 注释行是不被shell执行的。然而,shell脚本文件的第一行是个特例,井号后接叹号 告诉shell用哪个shell来运行脚本。
在指定了shell之后可在文件的每行输入命令,然后加一个回车符。之前提到过,注释可用井号添加 。
以# 号 开头的行都不会被shell处理 出了以(#!开头的第一行) 。
chmod u+x abc
10.3 显示消息
在bash脚本中可以使用echo 命令打印输出:
[root@centos1 ~]# echo This is a test
This is a test
如果在字符串中出现引号的话就可能比较麻烦,echo 命令可用单引号或使用双引号来将文本字符串圈起来。如果你再文本中使用一种引号,二用另外一种来将字符串圈起来:
[root@centos1 ~]# echo "Lets's go"
Lets's go
[root@centos1 ~]# cat abc
#!/bin/bash
echo "The time and date are:"
date;
who
[root@centos1 ~]# ./abc
The time and date are:
Sat Dec 9 11:05:23 CST 2017
root pts/0 2017-12-09 10:01 (192.168.20.224)
如果想在同一行显示一个文本字符串作为命令输出:可以使用echo -n 参数,只要将第一个echo语句改为这样就行。
[root@centos1 ~]# cat abc
#!/bin/bash
echo -n "The time and date are:"
date;
who
[root@centos1 ~]# ./abc
The time and date are:Sat Dec 9 11:07:16 CST 2017
root pts/0 2017-12-09 10:01 (192.168.20.224)
完美! echo 命令是shell脚本中桶用户交互的重要工具。
10.4.1 环境变量
[root@centos1 bash_dir]# cat test2
#!/bin/bash
echo "User info for userid : $USER"
echo UID : $UID
echo HOME : $HOME
[root@centos1 bash_dir]# ./test2
User info for userid : root
UID : 0
HOME : /root
注意,echo命令中的环境变量会在银杏是替换成当前值。还有在第一个字符串中我们可以将$USER系统变量放置到双引号中,而shell依然能够知道我们的意图。但采用这种方式也有一个问题,看看下面这个例子会怎样。
[root@centos1 bash_dir]# echo "The $15"
The 5
显然这不是我们想要的,要显示美元符,你必须在前面防止一个反斜线:
[root@centos1 bash_dir]# echo "The \$15"
The $15
反斜线允许shell脚本将美元符解释为实际的美元符,而不是变量。下一节将会介绍如何在脚本中创建自己的变量。
你可能还见过${variable} 形式引用的变量。变量名两侧额外的花括号通常用来帮助识别美元符后的变量名。
10.4.2 用户变量
除了环境变量,shell脚本还允许在脚本定义和使用自己的变量,定义变量允许临时存储数据并在整个脚本中使用,从而使shell脚本看起来更像计算机程序。
用户变量可以是任何不超过20个字母,数字或 下划线的文本字符串。 用户变量区分大小写,所以变量Var1和变量var1 是不同的。
值通过等号赋给用户变量。在变量、等号和值之间不能出现空格
- var1=10
- var2=-57
- var3=testing
- var4="Still more testing"
shell脚本会自动决定变量值的数据类型。在shell脚本的整个生命周期里,shell脚本中定义的变量会一致保持着它们的值,但在shell脚本完成时删除掉。
[root@centos1 bash_dir]# cat test3
#!/bin/bash
days=10
guest="Katie"
echo $guest "checked in $days"
[root@centos1 bash_dir]# ./test3
Katie checked in 10
10.4.3 反引号
shell脚本中最有用的特性之一就是反引号(`) .在shell脚本之外很少用到它,反引号允许你将shell命令的输出赋给变量。
你必须用反引号把这个命令行命令圈起来:
[root@centos1 bash_dir]# testing=`date`; echo $testing
Sat Dec 9 11:37:43 CST 2017
[root@centos1 bash_dir]# echo $testing
Sat Dec 9 11:37:43 CST 2017
[root@centos1 bash_dir]# (test=`date`; echo $test)
Sat Dec 9 11:38:31 CST 2017
[root@centos1 bash_dir]# echo $test[root@centos1 bash_dir]#
- 第一个定义命令列表,是在当前session中定义的用户变量
- 第二个是定义的进程列表,新创建一个进程,在进程里定义用户变量,出了该进程范围则输出为空
在脚本中通过反引号获得当前日期用用它来生成唯一文件名:
[root@centos1 bash_dir]# cat var1
#!/bin/bash
today=`date +%y%m%d`
ls /usr/bin -al > log.$today
[root@centos1 bash_dir]# ls
abc log.171209 test2 test3 var1
10.5 重定向输入和输出
有些时候你想要保存某个命令的输出而非在显示器上显示它。 bash shell提供了一些不同的操作符来将某个命令的输出重定向到另一个位置(比如文件)。重定向可以通过将某个文件重定向到某个命令上来用在输入上, 也可以用在输出上。
10.5.1 输出重定向
重定向最基本的类型是将命令的输出发到一个文件中。 bash shell采用大于号(>) 来完成这个功能
command > outputfile
之前显示器上出现的命令的输出会被保存到指定的输出文件中。
[root@centos1 bash_dir]# date > test3
[root@centos1 bash_dir]# cat test3
Sat Dec 9 11:51:58 CST 2017
重定向操作符创建了一个文件test3(通过默认的umusk设置), 如果输出文件已存在了,则这个重定向操作符会用新的文件数据覆盖已存在的文件。
有时需要将命令的输出追加到已有文件上 可以用双大于号(>>) 来追加数据:如果文件不存在则创建。
date >> test4
10.5.2 输入重定向
输入重定向和输出重定向正好相反。输入重定向将文件的内容重定向到命令,而非将命令的输出重定向到文件。
输入重定向符号是小于号(<) :
command wc 命令提供了对数据中文本的计数。 默认情况下&#xff0c;它会输出3个值&#xff1a; 通过将文本文件重定向到 wc 命令。 还有一种输入重定向的方法&#xff0c;成为内联输入重定向。 这种方法允许你在命令行&#xff0c;而不是在文件指定输入重定向的数据。内联输入重定向符号是双小于号(<<)。除了这个符号&#xff0c;你必须指定一个文本标记来划分要输入数据的开始和结尾。 你可以用任何字符串的值来作为文本标记。但在数据的开始和结尾必须一致&#xff1a; command < 在这个命令行上使用内敛输入重定向时&#xff0c;shell会用PS2 环境变量中定义的次提示符&#xff0c;来提示输入数据。下面是使用它的情况&#xff1a; 次提示符会一直提示输入更多的数据&#xff0c;知道你输入了作为文本标记的那个字符串值。wc 命令会对内联输入重定向提供的数据执行 行 词 和字节计数。 有时你需要发送某个命令的输出作为另一个命令的输入。可以用重定向&#xff0c;会有些笨拙 先输出linux系统上安装文件的列表到rpm.list文件中。 然后排序文件中的内容。 类似于反引号(&#96;) 管道的符号在 shell编程之外也很少用到。管道放在命令键&#xff0c;将一个命令的输出重定向到另一个上&#xff1a; command1 | command2 不要以为管道连接会一个一个地运行&#xff0c;Linux系统实际上会同时运行这两个命令&#xff0c;在系统内部将它们连接起来。在第一个命令产生输出的同时&#xff0c;输出会被立即送到第二个命令。传输数据不会用到任何中间文件或缓冲区。 可以在一条命令中使用任意多条管道&#xff0c;可以继续将命令的输入通过管道传给其他命令来简化操作。 在shell脚本中有两种痛经进行数学运算操作 可以处理数学表达式&#xff0c;但是特别笨拙。 var1&#61;&#96;expr 1/2&#96; bash shell 为了保持跟Boume shell的兼容而包含了expr命令。但它同样也提供了一个执行数学表达式的更简单的方法。 bash中 将一个数学运算结果赋给某个变量时&#xff0c;你可以用美元符和 方括号($[operation]) 将数学表达式圈起来&#xff1a; 同样&#xff0c;注意在使用方括号来计算公式时&#xff0c;不用担心shell会误解乘号或其他符号&#xff0c;shell知道它不是通配符&#xff0c;因为它在方括号内。 bash shell数学运算只支持整数&#xff0c;如果要进行任何数学运算&#xff0c;这是一个巨大的限制。 使用内建的bash计算器&#xff0c;称作bc。 bash计算器其实是允许在命令行输入浮点表达式、解释表达式、计算并返回结果的一种编程语言。bash计算器能够识别&#xff1a; 你可以在shell提示符下通过bc命令访问bash 计算器&#xff1a; 浮点运算是由一个内建的成为scale的变量控制的。你必须将这个字设置为结果里你想要的小数后的位数&#xff0c;否则你不会得到想要的结果的&#xff1a; scale变量默认值是0 &#xff0c; 在scale值被设置前&#xff0c;bash计算器提供的答案没有小数点后的位置。在将其设置为4之后&#xff0c;bash计算器显示的答案有4位小数。-q命令行参数会将bash计算器输出的很长的欢迎条屏蔽掉。 出了普通数字&#xff0c;bash计算器还能支持变量&#xff1a; 可以使用反引号来运行bc命令并将输出赋给一个变量。 variable&#61;&#96;echo "options;expression" | bc&#96; 这里有个在脚本中使用它的例子&#xff1a; 这个例子在scale变量设置成了四位小苏&#xff0c;并未表达式指定了特定的运算。 脚本中定义了两个变量&#xff0c;它们都可以用在表达式中发送给bc命令。使用美元符来表示变量的值而不是变量自身&#xff0c;这个脚本输出如下&#xff1a; 这个方法适用于较短的运算&#xff0c;但有时你会更多地和你自己的数字打交道。如果你有很多运算&#xff0c;在同一个命令行中列出多个表达式就会有点麻烦。 针对这个问题有个解决办法。bc命令能够识别输入重定向&#xff0c;允许你将一个文件重定向到bc命令来处理。然而这样也叫人困惑&#xff0c;因为你必须将表达式存储到文件中。 最好的办法是使用内联输入重定向&#xff0c;允许你直接在控制台重定向数据。在shell脚本中&#xff0c;你可以将输出赋给一个变量&#xff1a; EOF文本 字符串标识了内联重定向数据的开始和结尾。记住仍然需要反引号来将bc命令的输出赋给变量。 将每个选项和表达式放在脚本中不同的行中&#xff0c;可以让事情变得更清晰&#xff0c;也更容易阅读和跟进。EOF字符串标识了内联重定向给bc命令数据的起始和结尾。当然&#xff0c;你也要用反引号来标识输出要赋给变量的命令。 bash运算器中创建的变量只在bash计算器中有效&#xff0c;不能再shell脚本中使用。 我们的实例脚本那种总是匆忙结尾&#xff0c;在运行完最后一条命令时&#xff0c;就结束了脚本。这里还有一个更好的结束事情的办法。 shell中运行的每个命令都是使用退出状态码(exit status) 来告诉shell它完成了处理。退出状态码是一个0~255 之间的整数值&#xff0c;在命令结束运行时由命令传给shell&#xff0c;你可以捕获这个值并在脚本中使用。 Linux提供了 $? 专属变量来保存上个执行的命令的退出状态码。必须在要查看的命令之后马上查看或使用$?变量。它的值会变成shell中执行的最后一条命令的退出状态码&#xff1a; 无效命令会返回一个退出状态码127 。Linux错误退出状态码没有什么标准惯例。但有一些可用的参考&#xff0c;如下 默认情况下&#xff0c;shell脚本会以脚本中的最优一个命令的退出状态码退出&#xff1a; 你可以改变这个来返回你自己的退出状态码。exit命令允许你再脚本结束时指定一个退出状态码&#xff1a; 也可以在exit命令的参数中使用变量 exit $var 需注意使用exit时 参数值最大只能255 。 结果值是指定的数被256除的余数。 如果参数为300 余数则为44&#xff0c;它就成了最后的状态退出码。 [root&#64;centos1 bash_dir]# wc test24 16 82 test2
[root&#64;centos1 bash_dir]# wc
marker[root&#64;centos1 bash_dir]# wc <
> kajsdl
> lakjsdlfl
> askdfl
> lskfks
> s
> lksdf
> EOF7 7 46
[root&#64;centos1 bash_dir]# wc <
> ksdjfk
> iwerui
> aa3 3 2110.6 管道
rpm -qa > rpm.list
sort [root&#64;centos1 bash_dir]# rpm -qa | sort
[root&#64;centos1 bash_dir]# rpm -qa | sort | more
10.7 执行数学运算
10.7.1 expr命令
10.7.2 使用方括号
[root&#64;centos1 bash_dir]# (var&#61;$[1 &#43; 5];echo $var)
6
[root&#64;centos1 bash_dir]# (var&#61;$[1 &#43; 5];echo $var ; var2&#61;$[$var * 2]; echo $var2)
6
1210.7.3 浮点解决方案
1.bc的基本用法
[root&#64;centos1 bash_dir]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type &#96;warranty&#39;.
12 * 54
648
12 * 5.4
64.8
3.156 * (3&#43;5)
25.248
quit[root&#64;centos1 bash_dir]# bc -q
3.44/5
0
scale&#61;4
3.44/5
.6880
quit
[root&#64;centos1 bash_dir]# [root&#64;centos1 bash_dir]# bc -q
var1&#61;10
var*4
0
var1*4
40
var2&#61;var1/5
print var2
2
quit
[root&#64;centos1 bash_dir]# 2.在脚本中使用bc
[root&#64;centos1 bash_dir]# (variable&#61;&#96;echo "scale&#61;4;3.44/5" | bc&#96;; echo $variable)
.6880[root&#64;centos1 bash_dir]# cat calculate
#!/bin/bash
var1&#61;&#96;echo "scale&#61;4;3.44/5" | bc&#96;
echo "The answer is $var1"
[root&#64;centos1 bash_dir]# ./calculate
The answer is .6880
[root&#64;centos1 bash_dir]# [root&#64;centos1 bash_dir]# cat varcalcu
#!/bin/bash
var1&#61;100
var2&#61;45
var3&#61;&#96;echo "scale&#61;4;$var1/$var2" | bc&#96;
echo "The answer for this is $var3"
[root&#64;centos1 bash_dir]# ./varcalcu
The answer for this is 2.2222
[root&#64;centos1 bash_dir]# variable&#61;&#96;bc <
statements
expressions
EOF
&#96;[root&#64;centos1 bash_dir]# cat eof
#!/bin/bash
var1&#61;10.46
var2&#61;43.67
var3&#61;33.2
var4&#61;71
var5&#61;&#96;bc <
a1&#61;$var1*$var2
b1&#61;$var3*var4
a1&#43;bc
EOF
&#96;
echo "The final answer for this mess is $var5"
[root&#64;centos1 bash_dir]# ./eof
The final answer for this mess is 456.788210.8 退出脚本
10.8.1 查看退出状态码
[root&#64;centos1 bash_dir]# date
Sat Dec 9 14:57:41 CST 2017
[root&#64;centos1 bash_dir]# echo $?
0
[root&#64;centos1 bash_dir]# [root&#64;centos1 bash_dir]# sdkjf
-bash: sdkjf: command not found
[root&#64;centos1 bash_dir]# echo $?
127
[root&#64;centos1 bash_dir]#[root&#64;centos1 bash_dir]# date %t
date: invalid date &#96;%t&#39;
[root&#64;centos1 bash_dir]# echo $?
1
[root&#64;centos1 bash_dir]# 10.8.2 exit命令
[root&#64;centos1 bash_dir]# ./eof
The final answer for this mess is 456.7882
[root&#64;centos1 bash_dir]# echo $?
0
[root&#64;centos1 bash_dir]# [root&#64;centos1 bash_dir]# cat test10
#!/bin/bash
var1&#61;20
var2&#61;10
var3&#61;&#96;bc <
EOF
&#96;
echo "The answer is $var3"
exit 5
[root&#64;centos1 bash_dir]# ./test10
The answer is 20
[root&#64;centos1 bash_dir]# echo $?
5