shell 脚本 | 字节青训营笔记

127 阅读9分钟

一、什么是shell

1、定义:

shell 是一个命令行解释器,它为用户提供了与操作系统交互的接口。用户可以在 shell 中输入命令,然后由 shell 解释并执行这些命令。直白的说,shell 就是一个程序,它允许用户通过命令行与计算机操作系统进行交互。用户可以在 shell 中输入命令,然后 shell 会解释并执行这些命令,完成各种任务。

2、用途

shell 还提供了许多高级功能,例如命令历史、命令补全、命令别名、脚本编程等。这些功能可以帮助用户更快捷、更高效地使用操作系统。

3、shell主要种类

常见的 shell 包括 Bourne shell(sh)、Bourne Again shell(bash)、C shell(csh)、Z shell(zsh)等。不同的 shell 有不同的特性和语法,但它们都提供了基本的命令行解释功能。

二、shell的执行方式

当 shell 执行一个外部命令时,它通常会创建一个子进程来执行这个命令。这种方式称为子进程执行。

例如,假设我们在 shell 中执行 ls 命令。shell 会创建一个子进程,并在这个子进程中执行 ls 命令。当 ls 命令执行完成后,子进程会退出,然后 shell 会继续等待用户输入下一条命令。

子进程执行的优点是,即使子进程崩溃或被终止,父进程(即 shell)也不会受到影响,仍然可以继续运行。此外,父进程和子进程之间可以通过管道、重定向等方式进行通信,实现更复杂的功能。

有些情况下,shell 也可以直接执行命令,而不创建子进程。这种方式称为父进程执行

它通常发生在执行 shell 内置命令时。例如,cdechoexit 等命令都是 shell 内置命令,它们会直接由 shell 执行,而不会创建子进程。

父进程执行的优点是速度快,因为不需要创建子进程。但是,如果命令执行过程中出现错误,可能会影响到父进程(即 shell)的运行。

image.png

三、shell的配置文件读取

当 shell 启动时,它会读取一些配置文件来初始化环境。不同的 shell 有不同的配置文件,它们的位置和名称也不同。

例如,对于 bash shell,它会按顺序读取以下配置文件:

  • /etc/profile:系统级别的配置文件,对所有用户生效。
  • ~/.bash_profile~/.bash_login~/.profile:用户级别的配置文件,只对当前用户生效。bash 会按顺序查找这些文件,只读取第一个存在的文件。

当用户退出 bash shell 时,它还会读取 ~/.bash_logout 文件来执行一些清理操作。

对于其他类型的 shell,它们也有类似的配置文件。例如,zsh 会读取 /etc/zshenv~/.zshenv/etc/zprofile~/.zprofile 等文件。

用户可以在这些配置文件中设置环境变量、定义函数、创建别名等。这些设置会在 shell 启动时自动生效。

image.png

四、shell的命令执行机制

老师课程里说的是:字符解析,展开,查找命令、执行。这里再补充一下后面的两步--- 等待结果、返回结果。

展开来说:当用户在 shell 中输入一条命令并按回车键时,shell 会按照以下步骤执行这条命令:

  1. 解析命令行:shell 会对用户输入的命令行进行解析,将其分割成多个单词。每个单词都可以是命令、选项、参数或特殊字符(如管道符 |、重定向符 <> 等)。
  2. 查找命令:shell 会在环境变量 PATH 指定的目录中查找命令。如果找到了,就执行这个命令;否则,显示错误信息。
  3. 执行命令:如果命令是一个外部命令(即不是 shell 内置命令),则 shell 会创建一个子进程来执行这个命令。如果命令是一个内置命令,则 shell 会直接执行这个命令。
  4. 等待结果:如果命令是一个外部命令,则 shell 会等待子进程执行完成并返回结果。如果命令是一个内置命令,则 shell 会直接显示结果。
  5. 返回提示符:当命令执行完成后,shell 会显示一个提示符,等待用户输入下一条命令。

这就是 shell 命令执行的基本机制。当然,实际情况可能更复杂,因为 shell 还支持许多高级功能,例如管道、重定向、变量替换、命令替换等。

image.png

五、运算符和引用

这里图中很明确了,不做解释。

image.png

六、管道和重定向

在 shell 中,管道(pipe)是一种将多个命令连接起来的机制。它允许用户将一个命令的输出作为另一个命令的输入,从而实现复杂的操作。

管道使用竖线符号 | 来表示。例如,下面的命令使用管道将 ls 命令的输出作为 wc 命令的输入:

sh
复制代码
ls | wc -l

上面的命令会列出当前目录中的文件和目录,然后使用 wc 命令计算它们的数量。wc -l 命令会统计输入行数,因此最终结果就是当前目录中文件和目录的数量。

管道可以连接任意多个命令。例如,下面的命令使用两个管道将三个命令连接起来:

sh
复制代码
ls | grep '.txt' | wc -l

上面的命令会列出当前目录中的文件和目录,然后使用 grep 命令过滤出以 .txt 结尾的文件,最后使用 wc 命令计算它们的数量。最终结果就是当前目录中以 .txt 结尾的文件数量。

image.png

补充几个点,使用管道时需要注意:

  • 管道只能传递标准输出(stdout)。如果 cmd1 产生了错误输出(stderr),则这些输出不会被传递给 cmd2
  • 管道中的每个命令都是在一个单独的子进程中执行的。这意味着,如果 cmd1 修改了环境变量或当前目录,这些修改不会影响到 cmd2
  • 管道中的命令会同时执行。也就是说,cmd1 和 cmd2 会同时启动,而不是等待 cmd1 执行完成后再启动 cmd2
  • 如果管道中的某个命令失败(即退出状态非零),则整个管道的退出状态也是非零。但是,这并不会影响到其他命令的执行。也就是说,即使 cmd1 失败,cmd2 仍然会执行。

2、重定向

什么时候会触发重定向呢,

image.png

七、判断、选择命令

1、判断命令(官方的说法叫条件成立)

在 shell 中,test[[[ 都是用于判断的命令。

  • test 命令用于检查某个条件是否成立。例如,test -e filename 会检查文件 filename 是否存在。如果存在,则命令返回真(退出状态为 0);否则返回假(退出状态为非 0)。
  • [ 命令实际上是 test 命令的另一种写法。它的语法与 test 命令相同,只是需要在最后添加一个 ]。例如,[ -e filename ] 等同于 test -e filename
  • [[ 命令是一种扩展的测试命令,它提供了比 test[ 更多的功能。例如,它支持模式匹配和正则表达式匹配。它的语法与 [ 类似,只是需要在最后添加一个 ]]。例如,[[ -e filename ]] 等同于 [ -e filename ]

这些命令通常用于 shell 脚本中的条件判断。例如:

sh
复制代码
if [ -e filename ]; then
    echo "文件存在"
else
    echo "文件不存在"
fi

上面的脚本使用 [ 命令检查文件 filename 是否存在,然后根据检查结果执行不同的操作。

2、选择

shell主要的选择结构分别是 if else 语句和 case in 语句和if elif else。它们都是根据命令的退出状态来判断条件是否成立。写法如下图。

  1. if else 语句 最简单的用法就是只使用 if 语句,它的语法格式为:
sh
复制代码
if condition
then
    statement(s)
fi

condition 是判断条件,如果 condition 成立(返回“真”),那么 then 后边的语句将会被执行;如果 condition 不成立(返回“假”),那么不会执行任何语句。注意,最后必须以 fi 来闭合。

如果有两个分支,就可以使用 if else 语句,它的格式为:

sh
复制代码
if condition
then
    statement1
else
    statement2
fi

如果 condition 成立,那么 then 后边的 statement1 语句将会被执行;否则,执行 else 后边的 statement2 语句。

  1. if elif else 语句 Shell 支持任意数目的分支,当分支比较多时,可以使用 if elif else 结构,它的格式为:
sh
复制代码
if condition1
then
    statement1
elif condition2
then
    statement2
elif condition3
then
    statement3
……
else
    statementn
fi

注意,if 和 elif 后边都得跟着 then。

  1. case in 语句 case in 语句的语法格式为:
sh
复制代码
case 变量 in 
情况一)
    statement1;;
情况二)
    statement2;;
*)
    default statement;;
esac

image.png

八、循环

在 Shell 脚本中,常用的循环语句包括 for 循环、while 循环和 until 循环。for 循环通常用于遍历一组数据,while 循环和 until 循环则用于在满足条件的情况下重复执行一段代码。

举个例子 好的,这里是关于 Shell 中三种循环语句的具体含义和解释:

  1. for 循环 for 循环通常用于遍历一组数据,它的语法格式为:
sh
复制代码
for 变量 in 列表
do
    命令序列
done

其中,列表可以是一组数字、字符或字符串,也可以是一个命令的输出结果。for 循环会依次将列表中的每个元素赋值给变量,并执行命令序列。

  1. while 循环 while 循环用于在满足条件的情况下重复执行一段代码,它的语法格式为:
sh
复制代码
while 条件测试
do
    命令序列
done

其中,条件测试可以是一个命令或一组命令,也可以是一个逻辑表达式。当条件测试返回真时,while 循环会执行命令序列;当条件测试返回假时,while 循环结束。

  1. until 循环 until 循环与 while 循环类似,但它是在条件不满足的情况下重复执行一段代码,它的语法格式为:
sh
复制代码
until 条件测试
do
    命令序列
done

其中,条件测试可以是一个命令或一组命令,也可以是一个逻辑表达式。当条件测试返回假时,until 循环会执行命令序列;当条件测试返回真时,until 循环结束。

image.png