第二部分~
执行过程和原理
执行
- shell 脚本一般以 .sh 结尾,也可以没有,这是约定;第一行需要指定用什么命令解释器来执行
#! /bin/bash
#! /usr/bin/env bash
#!是内核识别并选择合适的解释器之后,将文本文件再交给解释器执行
- 启动方式
- 文件名运行
./filename.sh
- 解释器运行
bash ./filename.sh
source运行
source ./filename.sh
执行过程
- 字符解析
- 识别换行符、分号(
;)做行的分割 - 识别命令连接符(
||&&管道)做命令的分割 - 识别空格、tab符,做命令和参数的分割
-
shell 展开,例如
{1..3}解析为1 2 3 -
重定向,将stdin、 stdout、 stderr的文件描述符进行指向变更
-
执行命令
- builtin直接执行
- 非builtin使用
$PATH查找,然后启动子进程执行
- 收集状态并返回
这个架构就像一个流水线,可以在里面进行输入分析和解析
bash 会以一些特殊字符作为分隔符,将文本进行分段解析。最主要是回车还有分号";"。
在 bash 脚本中,用回车或分号作为一行命令结束的标志。这就是第一层级的解析,将大段的命令行进行分段。
符号拓展(使用各种方法,比如大括号 {} 、波浪符 ~ 、变量和参数的展开/替换、文件名展开),并最终执行命令(通过 shell 内置命令或外部命令)。
Shell 展开
大括号展开 (Brace Expansion) {...}
一般由三部分构成,前缀、一对大括号、后缀,大括号内可以是逗号分隔的字符串序列,也可以是序列表达式 {x..y[..incr]}
波浪号展开 (Tilde Expansion) ~
参数展开 (Shell Parameter Expansion) ${}
-
间接参数扩展
${!parameter},其中引用的参数并不是parameter而是parameter的实际的值 -
参数长度
${#parameter} -
空参数处理
${parameter:-word} # 为空替换
${parameter:=word} # 为空替换,并将值赋给$parameter变量
${parameter:?word} # 为空报错
${parameter:+word} # 不为空替换
- 参数切片
${parameter:offset}
${parameter:offset:length}
- 参数部分删除
${parameter%word}# 最小限度从后面截取word
${parameter%%word}# 最大限度从后面截取word
${parameter#word}# 最小限度从前面截取word
${parameter##word}# 最大限度从前面截取word
命令替换 (Command Substitution)
在子进程中执行命令,并用得到的结果替换包裹的内容,形式上有两种:$(...) 或 ...
数学计算 (Arithmetic Expansion) $((..))
使用 $(()) 包裹数学运算表达式,得到结果并替换
文件名展开 (Filename Expansion) *?[..] 外壳文件名模式匹配
当有单词没有被引号包裹,且其中出现了 '*','?', '[' 字符,则 shell 会去按照正则匹配的方式查找文件名进行替换,如果没找到则保持不变。
调试和前端集成
调试
- 普通 log,使用 echo,printf
- 使用 set 命令
- vscode debug 插件
VSCode 配置
-
shellman: 代码提示和自动补全
-
shellcheck: 代码语法校验
-
shell-format: 代码格式化
-
Bash Debug: 支持单步调试
- 安装vscode插件
- 编写launch. json文件
- 升级bash到4.x以上版本
前端集成
- node中通过
exec、spawn调用shell命令 - shell脚本中调用node命令
- 借助zx等库进行javascript、shell script的融合
- 借助shell完成系统操作,文件io、内存、磁盘系统状态查询等
- 借助nodejs完成应用层能力,网络io、计算等