11 构建基本脚本

11.1 创建shell脚本

创建shell脚本时,第一行必须指定要使用的shell。#后面的惊叹号会告诉shell用哪个shell来执行脚本。

#!/bin/bash

11.2 显示消息

echo命令可以用单引号或者双引号划定字符串。但是如果字符串中要包含单引号或双引号,则划定的符号必须选用另一个。-n参数可以让echo输出的行尾没有换行符

#!/bin/bash
# This script displays the date and who's logged on
echo -n "The time and data are:"
date
echo "Let's see who's logged into the system:"
who

执行输出

The time and data are:2019年 8月22日 星期四 22时44分46秒 CST
Let's see who's logged into the system:
leo console Aug 22 12:49
leo ttys000 Aug 22 12:49
leo ttys001 Aug 22 12:49
leo ttys002 Aug 22 12:49
leo ttys003 Aug 22 12:49
leo ttys004 Aug 22 12:49
leo ttys005 Aug 22 12:49
leo ttys006 Aug 22 12:49
leo ttys008 Aug 22 17:56

11.3 使用变量

环境变量

#!/bin/bash
# display user information from the system.
echo "User info for userid:$USER"
echo UID: $UID
echo HOME: $HOME

输出

User info for userid:leo
UID: 501
HOME: /Users/leo

可以看到$在字符串中也会引用变量。如果要把$当做一个字符输出,则需要用\$。另外,除了直接用$引用变量,还可以用${variable}的形式引用变量。

用户变量

注意变量、等号和值之间没有空格!

shell脚本会自动决定变量值得数据类型。在脚本的整个生命周期里,shell脚本中定义的变量会一直保持这个值,直到shell脚本运行结束被删除掉。

命令替换

即从命令的输出中提取信息,并将其值赋给变量。有两种方式

  • 使用反引号

  • $()

#!/bin/bash
# copy the /usr/bin directory listing to a log file
today=$(date +%y%m%d)
ls -la /usr/bin > log.$today

+%y%m%d可以养date的输出格式化,执行后我们可以看到当前目录多了一个文件log.190822(今天的日期是2019年8月22日)

注意命令替换会创建一个子shell来运行相应的命令。

11.4 输入输出重定向

输出重定向

>将输出写到一个文件中。如果想要不覆盖文件,而是追加,则使用>>

输入重定向

<将文件内容作为输入。另外<<是内联输入重定向(inline input redirection)。必须指定一个文本标记来划分输入数据的开始和结尾。

command << marker
data
marker

一个例子。wc输出的三个数字分别是文本的行数、词数和字节数。

$ wc << EOF
> test string 1
> test string 2
> test string 3
> EOF
3 9 42

11.5 管道

两个命令不是依次执行。linux实际上是同时运行两个命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据传输不会用到任何不中间文件或缓冲区。

11.6 执行数学计算

expr表达式

Bourne shell最初提供expr命令来处理数学计算。但是这个命令笨拙,且会错误理解一些字符。

方括号

bash兼容Bourne shell,保留了expr表达式,同时使用更简洁的方括号$[operation]

#!/bin/bash
var1=100
var2=45
var3=$[$var1 / $var2]
echo "The final result is $var3"

bash shell本身只支持整数运算,所以最后的输出是2

The final result is 2

bash计算器:bc

bc支持浮点运算。scale变量默认值是0,不包含小数位。设置成几,则包含几位小数。

$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
scale=5
var1=100
var2 = var1 / 3
print var2
33.33333

要在脚本中使用bc,我们可以用命令替换$()

#!/bin/bash
var1=20
var2=3.14159
var3=$(echo "scale=4; $var1 * $var2" | bc)
var4=$(echo "scale=4; $var3 * $var2" | bc)
echo "The final result is $var4"

输出

The final result is 197.39175

除了使用管道之外,还可以使用内联重定向

#!/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 "The final anwer for this mess is $var5"

结果是

The final anwer for this mess is 2813.9882

11.7 退出脚本

shell中每个命令结束时都有退出状态码。$?变量保存的是上一个执行的命令的退出状态码。状态码在0-255之间,如果超过会自动求模。shell脚本的退出状态码就是其执行的最后一个命令的退出状态码。

$ date
2019年 8月23日 星期五 00时54分31秒 CST
$ echo $?
0

一些常见的退出状态码

状态码

描述

0

成功结束

1

一般性未知错误,如参数无效

2

不适合的shell命令

126

不可执行,一般是权限denied

127

没有找到命令

128

无效的退出参数

128+x

与linux信号x相关的严重错误

130

ctrl+c终止的命令