Shell编程
Shell基础
大多数Linux发行版不安装桌面环境,需要使用Shell管理操作系统。
Shell是一个命令解释器,一次命令交互的过程为:Shell将用户输入的命令解释称Linux内核能够识别的命令,传递给内核执行,内核返回执行结果给Shell,Shell显示输出结果。
Shell分类:
- GUI图形界面Shell
- CLI命令行Shell 通常所说的Shell是这种
Shell命令的各种组合形成了Shell脚本(Shell Scipt)。Shell脚本的主要内容就是各种命令,每个命令可以单独执行,经过一系列操作符的连接、判断、循环形成了新的编程语言。
Shell脚本中的‘’hello world‘’
创建并执行Shell脚本的基本流程:
- 文本编译器创建 .sh文件
- 写入代码
- 添加执行权限
- 执行
变量
Shell不严格区分变量类型,变量类型取决于内存中存储的内容。在第一次给变量赋值时决定变量类型。同时,未声明类型的变量,在赋值时会自动进行转换。
变量声明
变量赋值
-
使用
=
赋值变量名=变量值
-
read交互变量赋值
read 变量名 # 执行后即可在终端输入变量值
变量引用
语法
$变量名 # 最简便
${变量名} # 适用在变量名之后还有其他字符在
"$变量名" # 避免变量值中空格的干扰
"${变量名}" # 避免变量值中空格的干扰
变量分类
-
内部变量 如
?
-
环境变量
每个操作系统都会有默认的变量,称为环境变量。可以使用export查看
-
参数变量
参数变量是用户在代码编写过程中自定义的变量。
Shell中的引号
在Shell中,对字符串并没有严格的引号要求。如果字符串中包含有空格,那么就需要经字符串包含到引号中去。因为空格后的字符可能被当做命令的选项或参数,可能会出错。
-
示例,定义变量并赋值含有空格的字符串
【注意】双引号之中对变量的引用能够正常的输出变量值;单引号之中对变量的引用不能正常的输出变量值。
所以有时不想引用变量值可以使用单引号。
变量的间接引用
间接引用,是指某个变量的值是另外一个变量的变量名的情况。Shell使用!
操作符实现间接引用。
-
示例 变量的间接引用
命令别名
在Shell的使用过程中,很多时候会遇到很长的命令。可以起别名进行替换。
语法
alias newname=command
-
示例
运算符
算术运算符
Shell中常用的算术运算符
++、--
+、-
*
/
%
-
示例
位运算符
Shell中常见的位运算符
~ # 按位取反
<<、>> # 左移、右移
& # 按位与
^ # 按位异或
| # 按位或
逻辑运算符
使用逻辑运算符可以实现多个条件的测试。
-a # 逻辑与
-o # 逻辑或
! # 逻辑非
&& # 逻辑与
|| # 逻辑或
-
示例 测试逻辑元素运算符
三元运算符
三元运算符?
,语法
表达式1 ? 表达式2 : 表达式3
# 表达式1 条件判断
# 如果未真 输出表达式2
# 如果为假 输出表达式3
三元运算符需要三个表达式。
赋值运算符
注意赋值运算符左右两侧不可以有空格
运算符优先级
let命令
let是Shell中的内部命令,功能是计算一个算术表达式。
语法
let 表达式
-
示例 使用let进行计算
其他常见表达式
除了let命令外,还有由符号组成的表达式运算操作,这些语法更常用更方便
语法
$((表达式))
$[表达式]
条件测试
在Shell中通过成条件判断为条件测试。
条件测试语法
Shell支持三种条件测试语法
test conditicon # test内部命令,检测表达式是否为真,返回TRUE or False
[ condition ] # 常用,注意条件左右距离 [] 有一个空格
[[ condition ]] # 比第二种更严谨,第二种有时候会出错
文件测试
文件测试主要是判断
- 文件是否存在
- 文件属性是否满足条件
常用操作如下:
-d file # 检测是否是目录,如果是。返回true
-f file # 检测是否是文件,如果是。返回true
-r file # 检测文件是否可读,如果是,返回true
-w file # 检测文件是否可写,如果是,返回true
-x file # 检测文件是否可执行,如果是,返回true
-s file # 检测文件是否为空,不为空返回true
-e file # 检测文件(包括目录)是否存在,如果存在返回true
【注意】在条件测试时,0为真、1为假,与大多数编程语言相反。
- 示例,判断某个文件是否为目录
[-e pp]命令的返回结果 自动复制给?
操作符,(?
操作符是一个特殊变量,作用是保存上一次命令执行的返回值)
,适用$
操作符引用并输出结果。
此时的输出结果为0,也就是真值,pp文件时一个目录。
字符串测试
常用的字符串操作符如下
< # ASCII顺序,前面的字符串小于后面的字符串为真
> # 大于
== # 字符串完全相同为真
= # 字符串相等为真
=~ # 前面的字符串包含后面的字符串为真
!= # 字符串不相等为真
-z # 字符串为空则为真
-m # 字符串非空为真
【注意】以上所有操作符在使用时,必须两侧都有空格才可以。在赋值时,两侧都不可以有空格。
- 示例 测试字符串比较操作符
-
示例 对比两个字符串类型的变量
整数值的测试
Shell对整数值的测试是使用字符操作符,而不是常用的算术运算符。
常用的操作符如下:
-eq # 两个数相等为真
-ge # 前者大于等于后者为真
-gt # 前者大于后者为真
-le # 前者小于等于后者为真
-lt # 前者小于后者为真
-ne # 两个数不相等为真
-
示例 整数值测试
分支语句
if语句
if语法
if [条件测试];then +
条件测试为真时执行语句
elif [条件测试];then
条件测试为真时执行语句
else 上述测试都为假时执行该语句
fi
同上,shell脚本中每一行一条语句即可执行。如果想将多条语句写在同一行,需要使用;
分割。
-
示例,if判断pp文件是否存在

语句
;;
"var2")
语句
;;
"var3")
语句
;;
*)
语句
;;
esac
变量值为需要判断的值,var1-var3为匹配条件,case结构在执行时,Shell会一次将变量值与后续的匹配条件进行匹配。如果有匹配,则执行匹配后的语句,如果全部不匹配,则执行*代表的分支,如果没有*分支,则直接退出执行。
case结构中,行尾必须是in
关键词,每个匹配条件后必须有一个)
,每个条件分支都有两个连续的;
,表示分支结束。
- 示例,case判断字符串
case匹配中,可以使用正则表达式。
-
示例,使用正则表达式的case匹配

# ass_array是关联数组的数组名称
-
示例 创建关联数组
函数
Shell支持函数的创建与调用,当脚本过于复杂时,可以提取程序的某些功能,形成一个函数模块,通过函数调用实现某个功能。
函数定义
语法
function 函数名()
{
函数体
}
-
示例,定义两个函数并进行调用

{
$1
$2
}
函数名 参数1 参数2 # 在这里传入参数
-
示例

,
-
示例,定义两个函数,分别实现默认返回值和自定义返回值
文本处理
格式化输出
格式化输出能够把输出的内容根据指定的格式输出,自动对齐、换行等操作。格式化输出内容使用的是printf
指令。
语法
printf format-string [arguments…]
# format-string 格式化字符串操作
# [arguments…] 参数字符串,待输出美容
【注意】转义字符只在格式字符串中会被特别对待,出现在参数字符串里的转移字符不会被解释、
常见格式化字符如下
\t # 水平tab 键
\v # 垂直tab 键
\n # 换行
\r # 回车, Enter键
\f # 清除屏幕
\b # 输出退格键
\a # 输出警告声音
%ns # 输出字符串: 输出n位的字符串
%ni # 输出整数: 输出n位的整数
%m.nf # 输出浮点数: m位整数 和 n位小数
-
示例
sed命令 未看
sed处理替换文本的需求。如,某个词首字母大写。
sed可以进行替换、删除、新增、选取等特定工作,sed命令常用选项及操作如下。
-n # 使用安静模式
-e # 直接在命令列模式上进行编辑
-f # 将sed命令输出到文件中,通过执行该文件执行对应的sed命令
awk命令 未看
diff文本内容比较
diff语法
diff ver1 ver2
其中,ver1和ver2是相同的恩建,但是版本不同。对比结果会输出到终端中,也可以使用重定向的方式,将结果输出到指定文件中,形成修补文件。
-
示例,使用diff查看文件不同
-
输出内容共两部分,以第一部分为例。
第一行,第一个1代表第一个文件中的第一行,c代表change,第二个1代表第二个文件中的第一行;意思为第一行内容改变了
第二行,第一个文件第一行的内容。
<
用来标记,说明后面的东西是第一个文件的内容第三行,—分隔符
第四行,第二个文件第一行的内容。
>
用来标记,说明后面的东西是第二个文件的内容
`