Linux · 2023-11-08 0

《Linux命令行与shell脚本编程大全》读书笔记02

第十一章 构建基础脚本

11.1 使用多个命令

11.2 创建shell脚本文件

第一行必须要指定使用的shell,格式如下

一般#用作注释行,但脚本文件的第一行是个例外 #后的感叹号会告诉shell用哪个shell来运行脚本

在指明shell之后,可以在文件的各行输入命令,每行末尾加一个换行符

将以上文本保存到文件test1

要使shell找到脚本可采用以下两种方法

  1. 将放置shell脚本文件的目录添加到PATH环境变量中
  2. 在命令行中使用绝对路径或相对路径来引用shell脚本文件

使用./test来引用当前目录下的文件

注意修改权限保证有该文件的执行权限

11.3 显示消息

使用 echo命令在脚本中输出文本消息 — shell脚本中同用户交互的重要工具

一般使用无须使用引号划定字符串,也可用单引号或双引号划定字符串(尤其在字符串包含引号或空格时)

使用 -n 可将字符串和命令输出显示在同一行中

输出


11.4 使用变量

环境变量

用set查看环境变量

在脚本中,可以在环境变量名之前加上$来引用环境变量

echo命令中的环境变量会在脚本运行时被替换成当前值,(使用单双引号也一样)

要在字符串中显示’$’需要在前面加入反斜线

${variable}形式引用变量方便界定$后的变量名

输出:

用户自定义变量

名称是由字母 数字或下划线组成的字符串,长度不超过20个字符,变量名区分大小写

使用等号为变量赋值,变量、等号和值之间不能有空格!!

引用变量使要加$,对变量赋值时不加$

shell脚本会以字符串的形式存储所有的变量值,脚本中的各个命令可以自行决定变量值的数据类型

命令替换

shell脚本可从shell命令输出中提取信息并将其赋给变量,有两种方法:

  1. 反引号
  2. $() 格式

命令替换会创建出子shell来运行指定命令,这是一个由运行脚本的shell所生成的一个独立的shell,因此,在子shell中运行的命令无法使用脚本中的变量

date +%y%m%d 会提取日期信息,用200601格式显示

该脚本会将日期值赋给变量,再将其作为文件名的一部分。 日志文件的内容是/usr/bin目录内容的列表输出,脚本在不同日期运行,会产生不同名称的新文件

运行脚本后在目录下产生了文件 log.231101

11.5 重定向输入和输出

输出重定向

最基本的重定向会将命令的输出发送至文件,使用 ‘>’

要想不覆盖文件原有内容,只将输出追加到已有文件中,可用 ‘>>’

输入重定向

将文件的内容重定向至命令 ‘<

wc

可统计数据中的文本,默认输出三个值:文本的行数,文本的单词数,文本的字节数

内联输入重定向 ‘<<‘

无须使用文件进行重定向,只需在命令行中指定用于输入重定向的数据即可

必须指定一个文本标记来划分输入数据的起止。任何字符串都可以作为文本标记,但数据开始和结尾的文本标记必须一致

11.6 管道

管道连接:将命令输出直接传给另一个命令

linux系统会同时运行这两个命令,在系统内部将二者连接起来,将第一个命令产生的输出立即传给第二个命令

管道可以串联的命令数量没有限制,可以持续地将命令输出通过管道传给其他命令来细化操作

管道最常见的用法之一是将命令产生的大量输出传送给more命令

11.7 执行数学运算

expr

很多标准运算符在shell中有其他用法,需加 / 转义,使用较麻烦,不建议

使用方括号

只支持整数运算

zsh提供了完整的浮点数操作

浮点数解决方案 — bc

输入quit以退出

scale控制浮点数运算小数位数,默认值为0

在控制台中使用

-q 选项不显示bc的欢迎信息

bc也支持变量

在脚本中使用

以上的方法适用于较短的运算,但对大量运算而言很不方便,

更好的办法是使用内联输入重定向

在这个例子中,可在bash计算器中为变量赋值,其中创建的变量仅在计算器中有效,不能在shell脚本中使用

11.8 退出脚本

shell中运行的每个命令都使用退出状态码告诉shell运行完毕

退出状态码是一个0~255的整数值,在命令结束运行时由其传给shell

可获取这个值并在脚本中使用

查看退出状态码

Linux提供了专门的变量 $? 保存最后一个已执行命令的退出状态码。

按照惯例,成功结束的命令退出状态码为0;因错误而结束的命令,其退出状态码是一个正整数;无效命令会返回退出状态码127

常见错误:给命令提供无效参数的退出状态码为1

状态码描述
0命令成功结束
1一般性未知错误
2不适合shell的命令
126命令无法执行
127没找到命令
128无效的退出参数
128+x与linux信号x相关的严重错误
130通过Ctrl+C终止的命令
255正常范围以外的退出状态码

exit命令

在默认情况下,shell脚本会以脚本的最后一个命令的退出状态码退出

但exit命令允许在脚本结束时指定一个退出状态码

也可以使用变量作为exit的参数

但退出状态码最大为255

第十一章 结构化命令

12.1 if-then 、if-then-elif-then 与 if-then-else 语句

可嵌套

#或

if句会运行if之后的命令。 如果该命令的退出状态码为0,那么位于then部分的命令就会被执行 如果该命令的退出状态码是其他值,则then部分的命令不会被执行

fi语句用来表示if-then语句结束

then和else部分的命令都可以不止一条

示例1

输出:

示例2

输出:

12.4 test命令

if-then语句无法测试命令退出状态码之外的条件,但test命令可以

condition部分如果不写会返回非零的退出状态码 如果加入了条件 test命令会测试该条件

支持的条件有:

  1. 数值比较
  2. 字符串比较
  3. 文件比较

bash shell提供了另一种测试条件的方式,无须在if-then语句中写明test命令,

! 第一个方括号之后和第二个方括号之前必须留有空格

数值比较

比较描述
n1 -eq n2检查n1是否等于n2
n1 -ge n2检查n1是否大于或等于n2
n1 -gt n2检查n1是否大于n2
n1 -le n2检查n1是否小于或等于n2
n1 -lt n2检查n1是否小于n2
n1 -ne n2检查n1是否不等于n2

示例

输出:

注意:只支持整数

字符串比较

比较描述
str1 = str2检查str1是否和str2相同
str1 != str2检查str1是否和str2不同
str1 < str2检查str1是否小于str2
str1 > str2检查str1是否大于str2
-n str1检查str1的长度是否不为0
-z str1检查str1的长度是否为0
字符串相等性

比较时考虑所有的标点和大小写

字符串大小比较

注意1:大于号和小于号必须转义,否则会被视作重定向符,将字符串当做文件名

注意2:大于和小于顺序与sort命令所采用的不同 在比较测试中,大写字母被认为是小于小写字母的,但sort命令正好相反

结果:

输出无误,但脚本把大于号解释成了输出重定向,创建了文件zorbfootball,测试条件返回了退出状态码0,if认为条件成立

应改成if [ $string1 \> $string2]

字符串是非为零

-n -z

为被定义过的字符串也被视为长度为0

输出:

文件比较

测试linux文件系统中文件和目录的状态

应用非常广泛

比较描述
-d file检查file1是否存在且为目录
-e file检查file是否存在
-f file检查file是否存在且为文件
-r file检查file是否存在且可读
-s file检查file是否存在且非空
-w file检查file是否存在且可写
-x file检查file是否存在且可执行
-O file检查file是否存在且属当前用户所有
-G file检查file是否存在且默认组与当前用户的默认组相同
file1 -nt file2检查file1是否比file2新
file1 -ot file2检查file1是否比file2旧
  • 在将文件写入目录或准备切换到某目录前,用-d测试目录是否存在
  • 在更新文件前,用 -e 测试文件是否存在
  • 在尝试从文件中读取数据之前,先用 -r 测试文件是否可读
  • 在删除文件前,若不想删除非空文件,用 -s 检查文件是否为空
  • 在更新修改文件内容时,用 -w 测试文件是否可写
  • 若想在shell脚本中运行大量程序,用 -x 检查文件是否可以运行
  • 在编写软件安装脚本时,用 -nt -ot 判断文件新旧

注意:在使用-nt -ot时,不检查两文件是否都存在。若有文件不存在,那么返回信息可能存在错误

12.5 符合条件测试

用 && || 将布测试条件组合起来

  • [ condition1 ] && [ condition2 ]
  • [ condition1 ] || [ condition2 ]

输出:

if-then 高级特性

使用单括号

单括号允许在if语句中使用子shell

语法格式为

if (command) then commands

在这种情况下,bash shell会执行command之前,会先创建一个子shell,然后在其中执行命令。

若在if test语句中使用进程列表,退出状态码只取决于进程列表中的最后一个命令是否成功执行

使用双括号

双括号命令允许在比较过程中使用高级数学表达式

并且既能在if语句中使用,也能在脚本的普通命令中用来赋值

{{ expression }}

符号描述
val++后增
val–后减
++val先增
–val先减
!逻辑求反
~位求反
**幂运算
<<左位移
>>右位移
&位AND
|位OR
&&逻辑AND
||逻辑OR

输出:

使用双方括号

[[ expression ]]

可使用test命令中的标准字符串比较,还提供了模式匹配特性

模式匹配

可以定义通配符或正则表达式来匹配字符串

双等号 (==) 会将右侧的字符串视为一个模式并应用模式匹配规则

注意:不是所有的shell都支持双方括号

12.7 case命令

代替 if-then-elif-then-…-else 语句

case命令会采用列表格式来检查变量的多个值

星号会捕获所有与已知模式不匹配的值

示例: