shell基础笔记
1 变量
1.1 变量概论
-
变量名:
- 只包含字母、数字和下划线: 变量名可以包含字母(大小写敏感)、数字和下划线 _,不能包含其他特殊字符。
- 不能以数字开头: 变量名不能以数字开头,但可以包含数字。
- 避免使用 Shell 关键字: 不要使用Shell的关键字(例如 if、then、else、fi、for、while 等)作为变量名,以免引起混淆。
- 使用大写字母表示常量: 习惯上,常量的变量名通常使用大写字母,例如 PI=3.14。
- 避免使用特殊符号: 尽量避免在变量名中使用特殊符号,因为它们可能与 Shell 的语法产生冲突。
- 避免使用空格: 变量名中不应该包含空格,因为空格通常用于分隔命令和参数。
-
变量引用:$variable_name
-
变量边界:{variable_name}(尽量使用)
-
只读变量:readonly variable_name
-
删除变量:unset variable_name
-
变量类型 :
运行shell时,会同时存在三种变量:- 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 环境变量: 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
1.2 字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
1.2.1 定义
-
单引号
特点:- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
-
双引号
特点:
- 双引号里可以有变量
- 双引号里可以出现转义字符
注意:在shell脚本中,命令参数可以加双引号进行字符拼接,也可以不加双引号;区别在于空格是否会被认为参数分割符
-
反引号
特点:- 反引号里面可以写命令(会执行)
-
不用引号
特点:- 方便
- 可以有变量
1.2.2 一些例子
1 | 1. index查找子字符位置 |
2 比较测试
2.1 条件测试
test condition(与其他语言不同的是shell编程中,0表示真,1表示假)
1 | test -d dirname # 测试是否是目录 |
2.2 文件测试
文件测试,主要是判断文件是否符合指定的文件属性或文件是否存在
操作符 | 意义 |
---|---|
-b | 当文件存在,且为块文件时测试为 真 |
-c | 当文件存在,且为字符文件时测试 为真 |
-d | 当路径存在,且为目录时测试为真 |
-e | 当文件或目录存在时为真 |
-f | 当文件存在,且为普通文件时为真 |
-g | 当文件或目录存在,且设置了SGID 时为真 |
-h | 当文件存在,且为符号链接时为真 |
-k | 当文件或目录存在且设置了黏滞位 时为真 |
-p | 当文件存在,且为命名管道时为真 |
-r | 当文件或目录存在,且可读时为真 |
-S | 当文件存在,且其大小大于0时为真 |
操作符 | 意义 |
---|---|
-S | 当文件存在,且为套接字文件时为真 |
-t | 当文件是与终端设备相关联的文件描述符时为真 |
-u | 当文件或目录存在,且设置了SUID时为真 |
-w | 当文件或目录存在,且可写时为真 |
-X | 当文件或目录存在,且可执行时为真 |
当文件或目录存在,且被前进程有效用户时为真 | |
-G | 当文件或目录存在,且属于当前用户所在的用户 组时为真 |
file1ntfile2 | nt是new than的缩写,所以file1比file2新时为真 |
file1otfile2 | ot是old than的缩写,所以file1比file2旧时为真 |
file1effile2 | ef是equal from的缩写,所以当file1和file2为同 文件的硬链接是为真 |
例如:
[ -b /dev/doc ];echo $? # 测试/dev/doc是否为块文件,并打印返回值
(一定要注意中括号与变量之间要留有空格)
2.3 字符串测试
操作符 | 意义 |
< | 按ASCII码顺序,前面的字符串小于后面的字符串则为真 |
> | 按ASCII码顺序,前面的字符串大于后面的字符串则为真 |
= | 字符串完全相同为真;适用于[]和test(test和[]是等价的) |
== | 字符串完全相同为真;适用于[[]] |
=~ | 前面的字符串中包含后面的字符串时为真 |
!= | 字符串不相等为真 |
-Z | 字符串为空则为真 |
-n | 字符串非空为真 |
【注意】
- 以上左右操作符,在使用时,必须两侧都有空格才可以, 否则shell会将其中的操作符当做普通字符进行处理
- 字符串测试最好用双中括号[[]]
2.4 整数值测试
Shell中对整数值的测试使用的是字母操作符,而不是通常的算术运算符,常用的整数值测试操作符如下表所示:
操作符 | 意义 |
---|---|
-eq | equal to,两个数相等为真 |
-ge | greater than or equal to,前者大于等于后者为真 |
-gt | greater than,前者大于后者为真 |
-le | less than or equal to,前者小于等于后者为真 |
-It | less than,前者小于后者为真 |
-ne | no equal,两者不相等为真 |
附: | |
在 Bash 中,双方括号 [[ … ]] 用于条件测试。它提供了一些在单方括号 [ … ] 中不可用的高级条件测试功能,并且在使用时不需要进行字符串引号转义。双方括号通常用于更复杂的条件表达式。 |
3 语句
3.1 if语句
3.1.1 if……elif……else……(fi)
1 | if [ 条件测试 ];then |
3.1.2 if……else……(fi)
1 | if [ 条件测试 ];then |
注意:
-
在shell中空格用来分割不同的命令和参数:
- 注意if和[]之间的空格
- 条件和[]之间也要严格空格
- []中运算符号与变量也要严格空格隔开,否则会产生错误
-
else后面不需要引号和then
-
用&&、||、!连接不同条件时,再加一个[]
【示例】
1 | !/bin/bash |
3.2 case语句
case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
1 | case 值 in |
3.3 for循环
1 | 语法 |
3.4 while循环
1 | while 表达式 |
3.5 until循环
until循环结构在其他编程语言中并不常见。使用方法与前面讲的for循环和while循环结构类似,但是until是在条件测试为假时执行循环语句,直到条件测试为真时退出。
1 | until 表达式 |
3.6 select循环
select循环结构是Shell中比较特殊的一种循环结构,前面讲的循环结构中,大多有一个数组来保存各个元素,有时也不需要数组。而select循环结构中数组和变量时必须的,select循环是一个可以和用户进行交互式的循环结构,在命令行Shell中非常实用
1 | select var in list |
shell中continue、break语句和在python、c用法一样
四、数组
4.1 定义数组
- 数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似)。
- 与大部分编程语言类似,数组元素的下标由 0 开始。
Shell 数组用括号来表示,元素用"空格"符号分割开(数组可以换行,换行符不影响),语法格式如下:
1 | array_name=(value1 value2 ... valuen) |
4.2 访问数组:
1 | a=(1 2 3 4 5) |
注意:
- shell中赋值符号与变量和值之间不能有空格,否则会被认为三个不同命令或参数
- "#"操作符的作用位获取参数的长度,不仅可以获取数组的长度,对于变量也可以使用该操作符进行获取长度
4.4 数组切片
1 | Array1=${array[@]:m:n} |
4.5 数组替换
1 | {array[@]/from/to} |
4.6 关联数组
除了常见的下标索引形式的数组,Shell中还有一种被称为关联数组的数组形式,借助散列技术,使用字符串作为索引值,而不是使用数组作为索引
1 | ass array=([index]=vall [index1]=val2) |
4.7 遍历数组
1 | my_array=('Black' 'Copper' 'Crowntail' 'Dragon' 'Dumbo_Halfmoon' |
五、函数
5.1 定义
1 | function 函数名(){ |
5.2 函数的参数
函数参数是函数调用时,用以传递给函数的一些数据,Shell中函数可以接受多个参数。除了传递进来的参数外,每个函数中还都包含了一些内部参数,常用获取内部参数使用的,常见的内部参数符号如下所示:
符号 | 意义 |
---|---|
# | 传递到脚本的参数个数 |
* | 以一个单字符串显示所有向脚本传递的参数 |
$ | 脚本运行是的档期那进程ID号 |
l | 后台运行的最后一个进程ID号 |
@ | 与*相同,但是使用时加引号,并在引号中返回每个参数 |
- | 显示Shell使用的当前选项,与set命令功能相同 |
? | 显示最后命令的退出状态 |
六、文本处理命令
6.1 格式化输出
6.1.1 语法
格式化输出能够对把输出的内容根据指定的格式输出,自动进行对齐、换行等操作。格式化输出内容使用的是printf指令,printf指令常用的格式化字符如下所示
1 | 语法 |
6.1.2 格式化字符
格式说明符由 % 字符开始,后跟一个或多个字符,用于指定输出的格式。常用的格式说明符包括:
%s
:字符串%d
:十进制整数%f
:浮点数%c
:字符%x
:十六进制数%o
:八进制数%b
:二进制数%e
:科学计数法表示的浮点数
6.1.3 printf 的转义序列
序列 | 说明 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\c | 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略 |
\f | 换页(formfeed) |
\n | 换行 |
\r | 回车(Carriage return) |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 一个字面上的反斜杠字符 |
\ddd | 表示1到3位数八进制值的字符。仅在格式字符串中有效 |
\0ddd | 表示1到3位的八进制值字符 |
6.2 sed命令
sed是一个很好的文本处理工具,其本身是一个管道命令,主要是以行为单位进行文本文档的处理,可以将数据行进行替换、删除、新增、选取等特定工作。sed常用选项及功能如下所示:
1 | 语法 |
参数 | 作用 |
---|---|
-h | 显示帮助 |
-n | 使用安静模式 |
-v | 显示版本信息 |
-e | 以选项中指定的script(命令行)来处理输入的文本文件 |
-f | 以选项中指定的script(文件)来处理输入的文本文件 |
-r | 执行正则表达式的语法 |
-i | 直接修改读取的文件内容,而不是输出到终端 |
动作 | 作用 |
a | 新增行,a的后面可以是字符串 |
c | 取代行,c的后面可以是字符串 |
d | 删除行,通常后面不接参数,直接删除对应行 |
i | 插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); |
p | 打印,将某个选择的数据打印出,通常与-n选项一起运行 |
s | 替换,直接或通过正则表达式进行替换 |
6.3 awk命令
作为一款文本处理工具,awk被设计用于数据流,其不仅能够对行进行操作,还可以对列进行操作。awk命令有许多内建的功能,比如数组、函数等,具有很大的灵活性。
1 | 【语法】 |
6.4 diff命令
diff命令能够对两个文件进行详细的对比,并将差异结果进行重点标记,输出到文件中。输出到的文件成为被修补文件(patchfile),其中包含了修改过的、添加、删除的行及行号,用户可以通过修补文件对源文件进行更改。
1 | 【语法】 |