11.1 使用多个命令

使用 ; 分隔:

  • 最大命令行字符数: 255
  1. $ date ; who
  2. 2020 10 15 星期四 17:24:05 CST
  3. jdxj tty7 2020-10-14 18:35 (:0)

11.2 创建 shell 脚本文件

第一行指定使用哪种 shell:

  1. #!/bin/bash
  2. # This script displays the date and who's logged on
  3. date
  4. who

11.3 显示消息

echo:

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

11.4 使用变量

11.4.1 环境变量

显示环境变量:

$ set

使用环境变量:

  • 显示 $ 符号需要转义: \$
  • 其它引用形式: ${variable}
#!/bin/bash
# display user information from the system.
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME

11.4.2 用户变量

变量名规则:

  • 可以由字母, 数字, 下划线组成
  • 长度不超过20个
  • 区分大小写
  • 赋值时, 变量, 等号, 值之间不能有空格
#!/bin/bash
# testing variables
days=10
guest="Katie"
echo "$guest checked in $days days ago"
days=5
guest="Jessica"
echo "$guest checked in $days days ago"

11.4.3 命令替换

将命令输出赋给变量:

  • 使用 ```
  • 使用 $()
#!/bin/bash
testing=$(date)
echo "The date and time are: " $testing

生成唯一文件名:

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

注意:

  1. 命令替换会创建一个子 shell 来运行对应的命令。
  2. 子 shell (subshell) 是由运行该脚本的 shell 所创建出来的一个独立的子 shell (child shell)。
  3. 正因如此, 由该子 shell 所执行命令是无法使用脚本中所创建的变量的。
  4. 在命令行提示符下使用路径 ./ 运行命令的话, 也会创建出子 shell;
  5. 要是运行命令的时候不加入路径, 就不会创建子 shell。
  6. 如果你使用的是内建的 shell 命令, 并不会涉及子 shell。
  7. 在命令行提示符下运行脚本时一定要留心!

11.5 重定向输入和输出

11.5.1 输出重定向

如果文件存在, 将被覆盖:

$ date > test6

追加:

$ date >> test6

11.5.2 输入重定向

wc 命令默认输出三个值:

  • 行数
  • 词数
  • 字节数
$ wc < test6

内联输入重定向 (inline input redirection):

  1. <<
  2. 标记. 任何字符串都可作为起始/结束标记

次提示符:

  • 由 PS2 环境变量定义 ( heredoc> )
$ wc << EOF
heredoc> abc
heredoc> 123
heredoc> EOF
2 2 8

11.6 管道

重定向貌似只能是文件?

管道连接 (piping):

  • |
command1 | command2

注意:

  • 不要以为两个命令会依次执行
  • 不会使用中间的缓冲区

11.7 执行数学运算

11.7.1 expr 命令

expr 命令能够识别少数的数字和字符串操作符:

image.png

使用:

$ expr 1 + 5
6

特殊操作符需要转义:

$ expr 5 \* 2
10

在脚本中使用:

#!/bin/bash
# An example of using the expr command
var1=10
var2=20
var3=$(expr $var2 / $var1)
echo The result is $var3

11.7.2 使用方括号

在 bash shell 中使用 $[ operation ] :

$ var1=$[1 + 5]
$ echo $var1
6
$ var2=$[$var1 * 2]
$ echo $var2
12

在脚本中使用:

#!/bin/bash
var1=100
var2=50
var3=45
var4=$[$var1 * ($var2 - $var3)]
echo The final result is $var4

注意:

  • bash shell 只支持整数运算
  • z shell (zsh) 提供了浮点运算

11.7.3 浮点解决方案

1. bc 的基本用法

bash 计算器能够识别:

  • 数字 (整数, 浮点)
  • 变量 (简单变量, 数组)
  • 注释 ( # , /* */ )
  • 表达式
  • 编程语句
  • 函数

使用:

$ bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
12 * 5.4
64.8

设置保留小数的位数:

$ bc -q
3.44 / 5
0
scale=4
3.44 / 5
.6880

变量:

$ bc -q
var1=10
var1 * 4
40
var2 = var1 / 5
print var2
2

2. 在脚本中使用 bc

基本格式:

variable=$(echo "options; expression" | bc)

在脚本中使用:

#!/bin/bash
var1=$(echo "scale=4; 3.44 / 5" | bc)
echo The answer is $var1

结合变量:

#!/bin/bash
var1=100
var2=45
var3=$(echo "scale=4; $var1 / $var2" | bc)
echo The answer for this is $var3

利用内联输入重定向处理大量计算:

  • 在 bc 内联输入重定向中创建的变量不能在脚本中使用
#!/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 answer for this mess is $var5

11.8 退出脚本

  • 脚本中的每个命令都使用 “退出状态码” (exit status), 用于告诉 shell 已运行完毕
  • 范围0~255
  • 可以捕获 “退出状态码” 在脚本中使用

11.8.1 查看退出状态码

  • $?
$ date
2020年 10月 16日 星期五 16:37:23 CST
$ echo $?
0

一些可用的退出状态码参考:

image.png

11.8.2 exit 命令

  • shell 脚本使用其中最后一条命令的退出状态码作为该脚本的退出状态码

exit 命令可以指定退出状态码:

$ cat my_script.sh 
#!/bin/bash
# testing the exit status
var1=10
var2=30
var3=$[$var1 + $var2]
echo The answer is $var3
exit 5

可以使用变量:

  • 如果值超过255, 那么进行模运算: x%256
#!/bin/bash
# testing the exit status
var1=10
var2=30
var3=$[$var1 + $var2]
exit $var3

11.9 小结