主要参考视频:
这可能是B站讲的最好的Linux Shell脚本教程,3h打通Linux-shell全套教程,从入门到精通完整版_哔哩哔哩_bilibili
主要参考文档:
Shell 教程 | 菜鸟教程 (runoob.com)
Bash Shell教程 (yiibai.com)
先用视频入门,然后参考手册学习,之后实践总结。
认识Shell和Bash
计算机里,我们基本都会使用操作系统,对于开发人员来说,我们肯定需要控制操作系统做一些事情,但是有个问题,那就是出于安全性考虑我们用户层没法直接访问操纵系统的内核,这种情况下,就有人提出解决方案,那就是在内核操作上套一层“壳”,也就是Shell,然后提供给用户一些指令,用户层再通过指令去完成要干的活,这样,就避免了直接操作内核,保证了内核的安全性以及系统的稳定性。
Shell命令就是由此而来,Shell命令按照一定格式组成的文本就是Shell脚本。
那Bash是怎么回事呢?
有Shell命令,那肯定要有命令的解释器,也就是将输入的命令转换成实际操作系统内核要干的活,其中,Bash就是Shell命令的解释器。
有了一种解释器,肯定就有它的优点和缺点,必然就会出现其他种类的解释器,各有各的特点,各有各的适用场景,于是,市场上就出现了多种Bash。
事实上,不同的Bash对应的Shell也有些不同。
Linux中默认使用Bash,我们操作Linux就需要学习各种Bash Shell。
Linux操作系统中有不同类型的Shell。其中一些如下:
- Bourne Shell
- C shell
- Korn Shell
- GNU Bourne Shell
要想知道操作系统支持哪种Shell类型,可在终端中输入以下命令:
cat /etc/shells
要想知道bash在操作系统中的位置,可键入以下命令,将获得一个特定的位置:
which bash
如下:
显示的都是绝对路径。
Bash是Linux附带的标准Shell。它是当今最流行的开源Shell,并且具有在下一主题中阅读的各种生产功能。它也可用于Linux发行版,MacOS,Solaris 11和Windows 10。它通过许多改进为用户提供最佳体验。
Bash脚本
创建和执行
在计算机编程中,脚本是用于适当的运行时环境的一组命令,这些命令用于自动执行任务。
Bash Shell脚本是一个纯文本文件,其中包含一组通常在命令行中键入的各种命令。它用于在Linux文件系统上自动执行重复性任务。它可能包含一组命令或一个命令,或者可能包含命令式编程的标志,例如循环,函数,条件构造等。实际上,Bash脚本是用Bash编程语言编写的计算机程序。
如何创建和运行Bash脚本?
- 首先,使用
cd
命令进入保存脚本的目录;- (如果已有脚本则跳过,否则)使用
touch
命令创建零字节大小的脚本,脚本以.sh作为扩展名(经验证,不以.sh结尾也可以,事实上,linux中没有扩展名的概念,之所以常常写扩展名,是为了方便人为查看);touch file_name
- 打开文本,并输入bash脚本的shell命令;
- 使用chmod赋予该脚本以可执行的权限(这一步别忘了,要不文件没有可执行权限);
./file_name
来执行bash脚本(不在当前目录下就需要输入绝对路径或者相对路径);比如,创建一个脚本,并输入如下内容:
#! /bin/bash
echo Hello World!然后执行。
就会在终端打印出Hello World!
开头
每个基于Bash的Linux脚本都以以下行开头:
#!/bin/bash
这里
#!
称为shebang,该行的其余部分是解释器的路径,用于指定bash shell在操作系统中的位置。shebang的格式很重要,格式不正确会导致命令工作不正常。因此,在创建脚本时,要始终记住SheBang格式的这两点:
- 它应该始终在脚本的第一行。
- 在
#!
和解释器的路径之间,#
之前不应有任何空格。经测试,貌似有空格也可以,不过,还是应当遵循标准规范。
注意,单独的#是注释。
注意,linux中路径是以撇/来分隔的,在windows下是以捺\作为分隔的。
echo
echo是bash中常用的linux命令
echo
是Bash中的内置命令,用于通过传递参数来显示标准输出。它是用于将文本/字符串行打印到屏幕上的最广泛使用的命令。echo命令 – 输出字符串或提取后的变量值 – Linux命令大全(手册) (linuxcool.com)
单独的echo可以打印出空行。
比如:
显示结果定向至某个文件,也就是将显示结果写到某个文件里,其中>是重定向符号。
echo "It is a test" > myfile
关于引号
关于有无引号?
如果字符串是个整体,其实可以不用引号,shell也能识别为一个字符串。
但是,当字符串中有空格时,就有问题了,这是因为Bash使用空格来确定单独的项目。 这种情况下,引号就可以用于处理带有空格字符的文本和文件名。
关于单引号和双引号?
使用简单的文本和字符串时,我们使用单引号或双引号都不会有任何区别
但是,当涉及到变量引用时,就有区别了。
shell变量扩展仅适用于双引号。如果在单引号中定义变量,则不会将其视为变量。
下面通过一个例子来理解这一点:
变量
变量部分内容可参考:
Shell 变量 | 菜鸟教程 (runoob.com)
之所以不能有空格,是因为bash是通过空格作为分隔的。
对于Bash,不必在变量声明时定义变量的数据类型。Bash变量是无类型的,只需通过分配其值来键入变量名称,它会自动判断数据类型。
如果将数字值分配给变量,它将自动转为整数工作,如果将字符值分配给该变量,则它将转为字符串类型。
year=2012 comp_name=yiibai
使用
echo
命令,通过在名称之前加上美元($
)号来读取它们,例如:echo $year echo $name
Shell或UNIX系统中都有两种类型的变量。
- 系统定义的变量
- 用户定义的变量
系统定义的变量
是由LINUX操作系统本身创建和维护的预定义变量。它们的标准约定是通常以大写字母进行定义。因此,每当看到以大写字母定义的变量时,很可能它们就是系统定义的变量。要了解系统中这些变量的列表,请在命令行终端上键入命令
env或者
printenv
用户定义的变量
这些变量由用户创建和维护。通常,这些类型的变量以小写形式定义。但是不强制的,也可以将变量名称写成大写。如下简单示例:
变量的操作
通常对Bash中的变量执行两个操作,如下所示:
- 为变量设置值。
- 读取变量的值。
设置变量值有几种方式,其中最常见的方法是直接设置值。
参考:Shell 变量 | 菜鸟教程 (runoob.com)
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。
推荐给所有变量加上花括号,这是个好的编程习惯。
Bash检查识别每个变量后,它将用分配的值替换每个变量名。它解释/运行每一行代码,并针对脚本的每个编码行继续执行此过程。
注:Bash中的两种变量都可以在终端以及Bash脚本上使用
只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
下面的例子尝试更改只读变量,结果报错:
删除变量
使用 unset 命令可以删除变量。语法:
获取字符串长度
数组
参考:Shell 变量 | 菜鸟教程 (runoob.com)
Shell 数组 | 菜鸟教程 (runoob.com)
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
定义数组
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值1 值2 ... 值n)例如:
array_name=(value0 value1 value2 value3)
传递参数
参考:Shell 传递参数 | 菜鸟教程 (runoob.com)
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为 $n,n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。
例如可以使用 $1、$2 等来引用传递给脚本的参数,其中 $1 表示第一个参数,$2 表示第二个参数,依此类推。
另外,还有几个特殊字符用来处理参数:
命令替换
其实就是获取命令执行的结果作为最终的内容。
替换的经典形式是使用反引号,如下所示:
也可以通过将命令放在圆括号(以美元符号(
$
)开头)中来进行命令替换。如下:示例:
读取用户输入
读取Bash用户输入,需要使用内置的Bash命令
read
。它用于从用户处获取输入并分配给变量。它仅从Bash shell中读取一行。以下是read
命令的语法。read <variable_name>
以下是从Bash脚本读取用户输入的示例:
运算符
Shell 和其他编程语言一样,支持多种运算符,包括:
- 算数运算符
- 关系运算符
- 布尔运算符
- 字符串运算符
- 文件测试运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):
反引号,其实就是将expr命令执行的结果作为最终的结果值。
两点注意:
- 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
- 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,而是在 Esc 键下边的反引号。
更多直接参考
Shell 基本运算符 | 菜鸟教程 (runoob.com)
注意:注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。注意,这里面有四个空格,从方括号开始后面就有空格了。
比较新奇的一个字符串运算符
条件语句-if
注意:在 sh/bash 里,如果 else 分支没有语句执行,就不要写这个 else分支。
Shell 流程控制 | 菜鸟教程 (runoob.com)
以if开头,以fi结尾。
有if就要搭配then,最后分支的else可以不用。
条件放在方括号[……]里。我看两个参考文档里,有的说条件后要加分号,有的又没有加,比较混乱。参考下这篇:shell中的if语句 - 开始认识 - 博客园 (cnblogs.com)
再参考这篇:
Shell if else语句(详解版) (biancheng.net)
可知:
当then和if处于同一行时,分号;才是必须的。
双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
注意:(( )) 只能进行整数运算,不能对小数(浮点数)或者字符串进行运算
选择语句-case
case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
case ... esac 语法格式如下:
更多参考:
Shell 流程控制 | 菜鸟教程 (runoob.com)
循环语句
Shell 流程控制 | 菜鸟教程 (runoob.com)
for循环 while循环 until循环
for循环
shell三种 for循环方式_shell 循环100次-CSDN博客
参考:
Bash for循环 - Bash Shell教程 (yiibai.com)
注意,for-in中列表是以空格来分开每一项。
更多直接参考:
Shell 流程控制 | 菜鸟教程 (runoob.com)
函数
直接参考即可:
Bash函数 - Bash Shell教程 (yiibai.com)
文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下: