Shell 脚本和编程 | 青训营笔记

234 阅读2分钟

Shell 脚本和编程

Shell基本概念

  • 终端:获取用户输入、展示运算结果的硬件设备
  • 终端模拟器:Mac Terminal、 iTerm2,关联虚拟 tty 的输入输出软件
  • Shell:command interpreter,处理来自终端模拟器的输入,解释执行之后输出结果给终端
  • tty:teletypeWriter的简称,和终端等价,早期指电传印机,在Linux是输入/输出环境
  • Bash | shell的一种具体体现

语法和命令

变量

类型作用域声明方式规范
自定义变量当前shell=字符串、整形、浮点型、日期型
环境变量当前shell及其子shellexport、declare -x
系统环境变量所有shell启动加载

父子shell, 类似于java中的父类调用子类的过程

image.png

自定义变量

以下代码为简单的赋值变量的例子

# 变量名等于变量值  
page_size=1
page_num=2  

# 将命令复制给变量  
_ls=ls

# 将命令结果赋值给变量  
file_list=$(ls -a)

# 默认字符串,不会进行 + 运算  
total=page_size*page_num   
# 上述段代码会计算错误

# 声明变量为整数 
let total=page_size*page_num

declare -i total=page_size*page_num  
# 上述正确

# 导出环境变量 
export total

declare -x total

注意:"="两边不能有空格!

declare 选项以及含义

选项含义
-给变量设置类型属性
+取消变量的类型属性
-a将变量声明为数组类型
-i将变量声明为整数类型
-x将变量声明为环境变量
-r将变量声明为只读变量
-p显示指示变量的被声明的类型

系统环境变量

变量名含义常见操作
$0当前shell 名称/脚本名称1,2等可以获取到传入参数
$1传入脚本的参数数量if[$# -gt1]
$*传入脚本的所有参数
$?上条命令执行的代码if[$? -eq0]
$PS1命令提示符export PS1="\u@h \w>"
$HOME用户主文件夹cd ~
$PATH全局命令的搜索路径PATH=$PATH:[新增路径]
  1. $#表示当前脚本或函数的参数个数。在shell脚本中,可以通过$#来获取当前脚本或函数的参数个数,并根据参数个数执行相应的操作。
  2. $*表示当前脚本或函数的所有参数列表。在shell脚本中,可以通过$*来获取当前脚本或函数的所有参数,并根据参数列表执行相应的操作。
  3. $?表示上一个命令的退出状态码。在shell脚本中,可以通过$?来获取上一个命令的退出状态码,并根据状态码执行相应的操作。
  4. $PS1表示shell提示符的格式。在shell中,可以通过修改$PS1来自定义shell提示符的格式,以适应个人习惯或需求。
  5. $HOME表示当前用户的主目录。在shell脚本中,可以通过$HOME来获取当前用户的主目录,并根据主目录执行相应的操作。
  6. $PATH表示系统的可执行文件路径列表。在shell中,可以通过修改$PATH来添加或删除系统的可执行文件路径,以便更方便地执行系统命令或自定义命令。

运算符与引用

image.png

管道

管道与管道符 | ,作用是将前一个命令的结果传递给后面的命令

语法:cmdi cmd2

要求:管道右侧的命令必须能接受标准输入才行,比如 grep 命令,ls、mv等不能直接使用,可以使用 xargs 预处理

注意: 管道命令仅仅处理 stdout,对于stderr 会予以忽略,可以使用 set -o pipefail 设置shell 遇到管道错误退出

#!/bin/bash

#该命令将文件platform.access.log的内容通过管道符|传递给grep命令,用于查找文件中包含字符串ERROR的行。这个命令的作用是在platform.access.log文件中查找错误信息
cat platform.access.log | grep ERROR 

#该命令使用netstat命令来显示所有的网络连接状态,并通过管道符|将结果传递给grep命令,用于查找所有处于ESTABLISHED状态的连接。最后,通过管道符|将结果传递给wc -l命令,用于统计行数。这个命令的作用是统计当前系统中所有处于ESTABLISHED状态的网络连接数量
netstat -an grep ESTABLISHED | wc -l

#该命令使用find命令在当前目录中查找所有扩展名为.sh的文件,并通过管道符|将结果传递给xargs命令,将查找到的文件名作为参数传递给ls -l命令,用于显示这些文件的详细信息。这个命令的作用是列出当前目录中所有扩展名为.sh的文件的详细信息
find . -maxdepth l -name "*.sh" | xargs ls -l

执行过程和原理

执行

shell脚本一般以.sh结尾,也可以没有。

启动方式三种:

  1. 文件名运行

    ./filename.sh

  2. 解释器运行

    bash ./filename.sh

  3. source运行
    source ./filename.sh

执行过程

  1. 字符解析
  2. shell 展开
  3. 重定向
  4. 执行命令
  5. 收集状态并返回

shell展开

  1. 大括号展开(Brase Expansion) {..}

一般由三部分构成:前缀,大括号,后缀 大括号展开是一种可以生成任意字符串的机制。展开大括号的模式采用可选的前缀,后接一系列逗号分隔的字符串或一对大括号之间的序列表达式,后接可选的后缀。前缀与大括号中包含的每个字符串组合,然后将后缀附加到每个结果字符串,从左到右展开。

  1. 波浪号展开(Tilde Expansion) ~

如果一个单词以未加引号的斜杠字符(’ ~ ')开头,则第一个未加引号的斜杠之前的所有字符(如果没有加引号的斜杠,则所有字符)都被视为波浪前缀。如果波浪号前缀中的字符都没有被引用,那么波浪号后面的波浪号前缀中的字符将被视为可能的登录名。如果这个登录名是空字符串,则用shell变量HOME的值替换波浪号。如果没有设置HOME,则替换执行shell的用户的HOME目录。否则,波浪前缀将被替换为与指定登录名关联的主目录。

  1. 参数展开
  • 间接参数扩展${!parameter}
  • 参数长度${#parameter}
  • 空参数处理:parameter:−word为空替换;{parameter:-word}为空替换;parameter:−word为空替换;{parameter:=word}为空替换,并赋值给parameter变量;parameter变量;parameter变量;{parameter:?word}为空报错;${parameter:+word}不为空替换。
  • 参数切片
  • 参数部分删除
  1. 命令替换

命令替换允许命令的输出替换命令本身。

  • $(...)
  • ...
  1. 数学计算(Arithmetic Expansion) $((..))

使用$(())包裹数学运算表达式,得到结果并替换。

  1. 文件名展开(Filename Expansion) ?[..]外壳文件名模式匹配 当单词没有被引号包裹,且出现' ' '?' '['字符,shell会按照正确的方式查找文件名替换,如果没找到保持不变。

调试和前端集成

调试

  1. 普通log,使用echo,printf
  2. 使用set命令
  3. vscode debug插件

image.png

VSCode配置

插件

  1. shellman:代码提示和自动补全
  2. shellcheck:代码语法校验
  3. shell-format:代码格式化
  4. Bash Debug:支持单步调试

前端集成

  1. node中通过exex ,spawn 调用shell命令
  2. shell脚本中调用node命令
  3. 借助zx等库进行javascript,shell script的融合

总结

image.png