Appearance
构建基本脚本
使用多个命令
shell脚本的关键在于输入多个命令并处理命令的结果
如果要一次使用多个命令可以放在一行中, 用冒号分割
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/10$ date; who
2022年 08月 05日 星期五 18:54:26 CST
jiao tty2 2022-08-05 15:37 (tty2)
只要不超过命令行最大字符数225就行
有一个很大的缺陷:每次运行之前,你都必须在命令提示符下输入整个命令。可以将这些命令组合成一个简单的文本文件,这样就不需要在命令行中手动输入了。在需要运行这些命令时,只用运行这个文本文件就行了
创建shell脚本文件
在创建脚本文件的时候要在第一行指定要使用的shell
bash
1 #!bin/bash
2 # 这个脚本展示了谁登陆了以及展示时间
3 date
4 who
#为注释, 但是会解释#!
要让命令行找到shell脚本, 要采用两种方法之一
- 将shell脚本文件所处的目录添加到PATH环境变量中;
- 在提示符中用绝对或相对文件路径来引用shell脚本文件
有些Linux发行版将$HOME/bin目录添加进了PATH环境变量。它在每个用户的HOME目录下提供了一个存放文件的地方,shell可以在那里查找要执行的命令
更改权限, 添加文件可执行权限
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ chmod u+x shelljb1
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb1
2022年 08月 05日 星期五 19:14:35 CST
jiao tty2 2022-08-05 15:37 (tty2)
显示信息
大多数的shell命令都会产生自己的输出, 这些输出会显示在运行的控制台显示器上, 如果想输出你在干什么, 可以使用
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ echo this is a string
this is a string
通常情况下不需要加引号, 但是当字符串中出现引号的时候就可Python处理一样, 文本中使用其中一种引号,而用另外一种来将字符串划定起来
bash
1 #!/bin/bash
2 # 这个脚本展示了谁登陆了以及展示时间
3 echo The tme and the date are
4 date
5 echo "Let's see who log in the system"
6 who
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb1
The tme and the date are
2022年 08月 05日 星期五 19:27:28 CST
Let's see who log in the system
jiao tty2 2022-08-05 15:37 (tty2)
如果要输出没有换行的语句
bash
echo -n "string"
使用双引号把对应的句子使用引号括起来
使用变量
用shell命令使用其他数据来处理信息, 变量允许临时性的储存信息
环境变量
在脚本中你可以使用环境变量,名再加上$来使用环境变量
bash
1 #!/bin/bash
2 # 打印操作系统使用者的信息
3 echo "User info for userid: $USER"
4 echo UID: $UID
5 echo HOME: $HOME
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ chmod u+x shelljb2
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb2
User info for userid: jiao
UID: 1000
HOME: /home/jiao
可以在字符串中使用$来输出变量
如果想输出一个美元符号, 需要输入
\$
你可能还见过通过${variable}形式引用的变量。变量名两侧额外的花括号通常用来帮助识别美元符后的变量名
用户变量
允许在shell脚本中定义自己的变量, 定义变量允许临时存放数据在整个脚本使用
用户变量可以是任何由字母、数字或下划线组成的文本字符串,长度不超过20个。用户变量区分大小写
使用等号将值赋给用户变量。在变量、等号和值之间不能出现空格
bash
var1=10
var2=-57
var3=testing
var4="still more testing
全局变量, 使用$引用
bash
1 #!/bin/bash
2 # 测试变量
3 days=10
4 guest="Katie"
5 echo "$guest check in $days days ago"
6 days=5
7 guest="Jessica"
8 echo "$guest check in $days days ago"
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb3
Katie check in 10 days ago
Jessica check in 5 days ago
变量每次被引用时,都会输出当前赋给它的值。重要的是要记住,引用一个变量值时需要使用美元符,而引用变量来对其进行赋值时则不要使用美元符
替换命令
shell最有用的特性之一就是可以从命令中提取信息, 并把值赋值给变量, 然后可以在脚本之中使用
有两种方法
- 反引号字符(`)
- $()格式
命令替换允许你将shell命令的输出赋给变量。尽管这看起来并不那么重要,但它却是脚本编程中的一个主要组成部分
- 用一对反引号把整个命令行命令围起来
bash
testing=`data`
- 要么使用$()格式
bash
testing=$(date)
shell会运行命令替换符号中的命令,并将其输出赋给变量testing
也可以直接把上面的格式加入到字符串中, 直接输出
bash
1 #!/bin/bash
2 testing=`date`
3 echo "the date is $testing"
4
5 testing2=$(date)
6 echo "the date is $testing2"
jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb4
the date is 2022年 08月 05日 星期五 20:04:38 CST
the date is 2022年 08月 05日 星期五 20:04:38 CST
在脚本中通过命令替换获得当前日期并用它来生成唯一文件名
bash
1 #!/bin/bash
2 # copy the /usr/bin directory listing to a log file
3 today=$(date +%y%m%d)
4 ls /usr/bin -al > log.$today
**注:(存疑)命令替换会创建一个子shell来运行对应的命令。子shell(subshell)是由运行该脚本的shell所创建出来的一个独立的子shell(child shell)。正因如此,由该子shell所执行命令是无法使用脚本中所创建的变量的
在命令行提示符下使用路径./运行命令的话,也会创建出子shell;要是运行命令的时候不加入路径,就不会创建子shell。如果你使用的是内建的shell命令,并不会涉及子shell。在命令行提示符下运行脚本时一定要留心
bash1 #!/bin/bash 2 # copy the /usr/bin directory listing to a log file 3 today=$(date +%y%m%d) 4 ls /usr/bin -al > log.$today 5 ps --forest 6 echo "$(ps --forest)" 7 echo "$(echo "$today")" jiao@jiao-virtual-machine:~/桌面/linux-shell/11$ shelljb5 PID TTY TIME CMD 2349 pts/0 00:00:00 bash 4583 pts/0 00:00:00 \_ shelljb5 4586 pts/0 00:00:00 \_ ps PID TTY TIME CMD 2349 pts/0 00:00:00 bash 4583 pts/0 00:00:00 \_ shelljb5 4587 pts/0 00:00:00 \_ ps 220805
重定向输入输出
命令输出不只显示在显示器上
bash shell提供了几个操作符,可以将命令的输出重定向到另一个位置(比如文件)
重定向可以用于输入,也可以用于输出,可以将文件重定向到命令输入。
输出重定向
bash
command > outputfile
之前显示器上输出的命令会被保存到指定的文件
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ date > test
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ ls -l
总用量 4
-rw-rw-r-- 1 jiao jiao 43 8月 5 20:58 test
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ cat test
2022年 08月 05日 星期五 20:58:45 CST
创建的文件通过umask设置
如果输出的文件已经存在, 会覆盖之前的内容
追加: 使用>>
输入重定向
将文件的内容输出到重定向的命令之中
wc命令可以对对数据中的文本进行计数。默认情况下,它会输出3个值:
- 文本的行数
- 文本的词数
- 文本的字节数
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ wc < test
3 16 135
还有另外一种输入重定向的方法,称为内联输入重定向
内联输入重定向符号是远小于号(<<)。除了这个符号,你必须指定一个文本标记来划分输入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致
bash
command << marker
data
marker
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ wc << EOF
> 123
> 321
> 213
> EOF
3 3 12
次提示符会持续提示,以获取更多的输入数据,直到你输入了作为文本标记的那个字符串
管道
把一个命令的输出当成另一个命令的输入
bash
command1 | command2
把第一个命令的输出传给第二个
通常使用把输出导入到more, 分页查看
执行数学运算
expr命令
可以识别少量的数学和字符串操作符
bash
#!/bin/bash
# An example of using the expr command
var1=10
var2=20
var3=$(expr $var2 / $var1)
echo The result is $var3
对于那些容易被shell错误解释的字符,在它们传入expr命令之前,需要使用shell的转义字符(反斜线)将其标出来
bash
expr 5 \* 2
使用方括号
在传递变量的时候可以把他和$一同使用$[ operation ]
bash
1 #!/bin/bash
2 var1=100
3 var2=50
4 var3=45
5 var4=$[$var1 * ($var2 - $var3)]
6 echo The final result id $var4
只支持整数的运算
z shell(zsh)提供了完整的浮点数算术操作。如果需要在shell脚本中进行浮点数运算,可以考虑看看z shell
浮点数解决方案
bash内建的计算器
bc基本用法
计算器实际上是一种编程语言
bash计算器能够识别:
- 数字(整数和浮点数)
- 变量(简单变量和数组)
- 注释(以#或C语言中的/* */开始的行)
- 表达式
- 编程语句(例如if-then语句)
- 函数
quit退出
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell$ 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'.
3.14 * 5 +0.01
15.71
浮点运算是由内建变量scale控制的。必须将这个值设置为你希望在计算结果中保留的小数位数,否则无法得到期望的结果
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell$ bc -q
3.14/5
0
scale=5
3.14/5
.62800
-q: 不显示欢迎信息
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell$ bc -q
var1=10
var2=20
var2/var1
2
var2=var1/4
vr2
0
print var2
2
使用print输出变量
在脚本中使用
可以用命令替换运行bc命令,并将输出赋给一个变量。基本格式如下:
bash
variable=$(echo "options; expression" | bc)
第一部分options允许你设置变量。如果你需要不止一个变量,可以用分号将其分开。expression参数定义了通过bc执行的数学表达式。
bash
1 #!/bin/bash
2 var1=$(echo "scale=4; 3.44/5" | bc)
3 echo The answer is $var1
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ test3
The answer is .6880
括号中的echo是为了把整个句子输出为参数
bash
1 #!/bin/bash
2 var1=100
3 var2=45
4 var3=$(echo "scale=4; $var1 / $var2" | bc)
5 echo The answer for this is $var3
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ test4
The answer for this is 2.2222
使用变量
上面的办法使用于比较短的运算
长运算时候bc可以识别重定向, 允许你把一个文件重定向到bc处理
bash
variable=$(bc<<EOF
options
statements
expressions
EOF
)
bash
1 #!/bin/bash
2 var1=10.46
3 var2=43.67
4 var3=33.2
5 var4=71
6 var5=$(bc<<EOF
7 scale=4
8 a1=($var1 * $var2)
9 b1=($var3 * $var4)
10 a1+b1
11 EOF
12 )
13 echo The final answer for this mess is $var5
退出脚本
shell中的每一个命令都使用退出状态码(exit status)告诉shell它已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用
查看退出状态码
Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码。
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ date
2022年 08月 05日 星期五 23:11:06 CST
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ echo $?
0
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ asd
Command 'asd' not found, but there are 22 similar ones.
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ echo $?
127
退出的时候出错, 就会产生一个大于零的状态码
无效命令127
没有特别的规定, 但是有一定的参考值
状态码 | 描述 |
---|---|
0 | 命令成功结束 |
1 | 一般性未知错误 |
2 | 不适合的shell命令 |
126 | 命令不可执行 |
127 | 没找到命令 |
128 | 无效的退出参数 |
128+x | 与Linux信号x相关的严重错误 |
130 | 通过Ctrl+C终止的命令 |
255 | 正常范围之外的退出状态码 |
126 没有相关的权限
1 参数错误
exit命令
默认情况下, shell会以脚本中最后一条命令状态码退出
exit命令允许你在脚本结束时指定一个退出状态码。
bash
1 #!/bin/bash
2 # 测试退出码
3 var1=10
4 var2=30
5 var3=$[$var1 + $var2]
6 echo The answer is $var3
7 exit 5
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ test6
The answer is 40
jiao@jiao-virtual-machine:~/桌面/linux-shell/11.5$ echo $?
5
**注:**输出的参数最大为255