学习shell的价值:

  1. Linux服务器的基本操作和办理
  2. 前端Node.js服务的进程办理、问题排查、资源监控等运维操作
  3. 运用shell编写TCE、SCM、Docker脚本,完结服务编译和部署

课程准备

  • 一台装置了 linux 体系的物理机或许云主机,可运转 shell 脚本
  • 本地的 vscode 装置 Bash Debug 插件,并晋级 bash 到4.x以上
  • Npm 大局装置 zx 依赖

Shell基本概念

概念

  • Shell(也称为指令行界面或终端)是一种经过文本输入和输出进行交互的核算机用户界面。它答应用户经过输入指令来履行操作、运转程序和办理体系

  1. 指令(Command):Shell经过输入指令来履行不同的操作或使命,例如创立文件、仿制文件、移动文件、运转程序等。指令通常由指令名和参数组成,指令名指定要履行的操作,参数用于指定指令的具体操作方法或效果目标。
  2. 提示符(Prompt):Shell在等待用户输入指令时会显现一个提示符,通常是一个特别的字符或字符串,表明Shell现已准备好接受指令输入。
  3. 文件体系(File System):Shell能够用于办理核算机上的文件和目录,包含创立、仿制、移动、删去、重命名、检查等操作。Shell运用文件体系的途径来定位文件和目录,例如绝对途径(从根目录开端的完整途径)和相对途径(从当时目录开端的相对途径)。
  4. 管道(Pipeline):Shell答应将多个指令经过管道衔接起来,其间一个指令的输出作为另一个指令的输入。这样能够完结多个指令的组合和协作,从而愈加灵敏地完结杂乱的使命。
  5. 环境变量(Environment Variable):Shell运用环境变量来存储体系级别的装备信息、用户装备和运转时参数。环境变量能够在指令中运用,并且能够经过设置和修正来影响Shell的行为和操作。
  6. 脚本(Script):Shell答应用户编写一系列指令的脚本文件,以便将一组指令作为一个单独的程序运转。脚本能够包含条件句子、循环、函数等控制结构,从而完结愈加杂乱的主动化使命。
  7. 快捷键(Shortcut):Shell供给了许多快捷键和指令行修正功能,用于提高指令行操作的功率和快捷性。例如,能够运用上下箭头键来阅读前史指令,运用Tab键进行指令和文件名的主动补全,运用Ctrl+C来中止正在履行的指令等。

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

  • Shell`和Bash`能够理解为类和实例的联系

Bash的进程

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

以下内容当作课外内容弥补(当故事看都行):

  1. 1989年:Bash由布莱恩福克斯(Brian Fox)开发,并初次发布。Bash基于Bourne Shell(sh),是Bourne Shell的一种改善版别,它增加了许多新的特性,例如指令前史、指令行修正、作业控制等。
  2. 1993年:Bash 1.12发布,这是Bash的榜首个公开发布版别。Bash开端在Unix和Linux体系中广泛传播,并成为默许的指令行Shell。
  3. 1994年:Bash 2.0发布,引入了更多的新特性,包含指令别号、条件句子、循环、函数、算术运算等,使Bash变得愈加强壮和灵敏。
  4. 2000年:Bash 2.05b发布,这是一个重要的版别,引入了许多新的特性,包含指令补全、目录堆栈、指令行参数处理等,进一步提升了Bash的用户友好性和交互性。
  5. 2007年:Bash 3.0发布,引入了更多的新特性,包含新的扩展特点、数组、相关数组等,使Bash愈加适用于杂乱的脚本编程和体系办理使命。
  6. 2011年:Bash 4.2发布,带来了许多新的特性和改善,包含新的内置指令、更强壮的方式匹配、更灵敏的前史指令办理、更高效的作业控制等。
  7. 2016年:Bash 4.4发布,带来了许多新的特性和改善,包含新的参数扩展、新的运算符、更好的过错处理、更强壮的指令前史办理等。
  8. 2019年:Bash 5.0发布,引入了一些新特性,例如新的管道重定向符号、新的内置指令、新的变量扩展和运算符等,继续改善和增强了Bash的功能和功能。

构成

Unix shell既是一个指令解说器也是一种编程语言。作为指令解说器,shell为丰富的GNU东西集供给了用户接口。

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

指令和语法

类型 效果域 声明方法 规范
自界说变量 当时shell =(隐式声明) 字符串、整型、浮点型、日期型
环境变量 当时shell及其子shell export declare -x(显现声明)
体系环境变量 一切shell 发动加载

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

自界说变量

#!/bin/bash
# 这是脚本文件的shebang,它告知体系脚本文件运用哪种解说器来履行。在这个比方中,运用的是bash解说器#变量名=变量值(等号左右不能有空格),界说了两个变量page_size和page_num,并别离给它们赋值为1和2
page size=1
page_num=2
​
#将指令仿制给变量,这样能够经过变量名来履行指令。
_ls=ls#将指令成果赋值给变量,能够经过变量名来访问指令成果
file_list=$(ls -a)
​
#默许字符串,不会进行 + 运算。所以total的值为"page_size*page_num"字符串
total=page_size*page_num
​
#声明变量为整型(-i),后续的数值核算中,total会被当作整型来处理
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、1、2等能够获取到传入参数
$# 传入脚本的参数数量 if[ $# -gt 1 ]
$* 传入脚本的一切参数
$? 上条指令履行的状况码 if [ $? -eq 0 ];
$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来增加或删去体系的可履行文件途径,以便更方便地履行体系指令或自界说指令。

装备文件加载

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

运算符和引证

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

管道

管道与管道符 | ,效果是将前一个指令的成果传递给后边的指令 语法:cmd1 | 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脚本和编程 | 青训营笔记

  • 修正了默许的联系

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

  1. >:将指令的输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则掩盖。
  2. >>:将指令的输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则在文件末尾追加。
  3. 2>:将指令的过错输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则掩盖。
  4. &>:将指令的输出和过错输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则掩盖。
  5. <:将一个文件的内容作为指令的输入。
  6. <<:将一段字符串作为指令的输入。

以下是一些比方:

  1. ls > file.txt:将ls指令的输出重定向到file.txt文件中,假如文件不存在则创立,假如文件现已存在则掩盖。
  2. ls >> file.txt:将ls指令的输出重定向到file.txt文件中,假如文件不存在则创立,假如文件现已存在则在文件末尾追加。
  3. ls 2> error.txt:将ls指令的过错输出重定向到error.txt文件中,假如文件不存在则创立,假如文件现已存在则掩盖。
  4. ls &> output.txt:将ls指令的输出和过错输出重定向到output.txt文件中,假如文件不存在则创立,假如文件现已存在则掩盖。
  5. sort < file.txt:将file.txt文件的内容作为sort指令的输入。
  6. cat << EOF:将下面的一段字符串作为cat指令的输入直到遇到EOF中止。

判别指令

shell中供给了test、[、[[三种判别符号,可用于:

  • 整数测验
  • 字符串测验
  • 文件测验

语法:

  • test condition
  • [ condition ]
  • [[ condition ]]

留意

  • 中括号前后要有空格符
  • [ 和test是指令,只能运用自己支撑的标志位,<、>、=只能用来比较字符串
  • 中括号内的变量,最好都是用引号括起来
  • [[更丰富,在整型比较中支撑<、>、=,在字符串比较中支撑=~正则

在shell中,test指令用于进行各种测验操作。在这段代码中,test指令被用于进行整数、字符串和文件的测验。

整数测验运用-eq-lt-gt选项来比较两个整数的巨细联系,回来成果为真或假。

字符串测验运用-z-n和`=“选项来测验字符串的长度、非空和相等联系,回来成果为真或假。

文件测验运用-e-f选项来测验文件是否存在和是否为一般文件,回来成果为真或假。在文件测验中,还能够运用-d选项来测验目录是否存在,-r选项来测验文件是否可读,-w选项来测验文件是否可写,-x选项来测验文件是否可履行等等。

#!/bin/bash# 整数测验
test $nl -eq $n2  # 测验 $nl 是否等于 $n2
test $nl -lt $n2  # 测验 $nl 是否小于 $n2
test $nl -gt $n2  # 测验 $nl 是否大于 $n2# 字符串测验
test -z $str_a   # 测验 $str_a 是否为空
test -n $str_a   # 测验 $str_a 是否非空
test $str_a = $str_b  # 测验 $str_a 是否等于 $str_b# 文件测验
test -e /dmt && echo "exist"  # 测验 /dmt 是否存在,并在存在时输出 "exist"
test -f /usr/bin/npm && echo "file exist"  # 测验 /usr/bin/npm 是否存在,并在存在时输出 "file exist"
  • 还有就是在进行比较的时分,需求留意的点:

    • 左边是写法,右边是写法实践上变成的内容样子

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

shell中的分支句子

在shell中,分支句子主要有if句子和case句子。

  1. if句子
  • if句子用于判别条件是否建立,假如建立则履行相应的指令或许代码块。if句子的基本语法如下:
if [ condition ]
then
   command1
   command2
   ......
   commandN
fi# condition是需求判别的条件,能够是变量、字符串、数值等,command1到commandN是需求履行的指令或许代码块
  • if句子能够带有else和elif句子,用于在条件不建立时履行相应的指令或许代码块。if句子的完整语法如下:
if [ condition ]
then
   command1
   command2
   ......
   commandN
elif [ condition2 ]
then
   command1
   command2
   ......
   commandN
else
   command1
   command2
   ......
   commandN
fi#condition是需求判别的条件,condition2是第二个需求判别的条件,command1到commandN是需求履行的指令或许代码块

事例演示:

需求:假设咱们需求判别一个数是否为偶数,假如是偶数则输出“偶数”,不然输出“奇数”。

解析:在这个比方中,咱们运用read指令获取用户输入的整数,然后运用$((num % 2))核算出余数,再判别余数是否等于0来判别这个数是否为偶数。假如是偶数则输出“偶数”,不然输出“奇数”

#!/bin/bashecho "请输入一个整数:"
read num
​
if [ $((num % 2)) -eq 0 ]
then
  echo "$num 是偶数"
else
  echo "$num 是奇数"
fi
  1. case句子

    case句子用于依据不同的条件履行相应的指令或许代码块

case variable in
pattern1)
   command1
   ;;
pattern2)
   command2
   ;;
......
*)
   commandN
   ;;
esac
​
# variable是需求判别的变量,pattern1到patternN是需求判别的方式,command1到commandN是需求履行的指令或许代码块。假如没有任何一个方式匹配,那么就会履行*后边的指令或许代码块。esac是用来结束的

事例演示:

需求:需求依据用户的输入来履行不同的指令

解析:咱们运用read指令获取用户的挑选,然后运用case句子依据不同的挑选履行相应的指令。假如用户挑选了1,则履行uname -a指令,假如挑选了2,则履行df -h指令,假如挑选了3,则履行free -m指令,假如挑选了4,则退出脚本。假如用户输入了无效的挑选,则输出“无效的挑选

#!/bin/bashecho "请挑选一个操作:"
echo "1. 显现体系信息"
echo "2. 显现磁盘运用情况"
echo "3. 显现内存运用情况"
echo "4. 退出"read choice
​
case $choice in
1)
   uname -a
   ;;
2)
   df -h
   ;;
3)
   free -m
   ;;
4)
  exit 0
   ;;
*)
  echo "无效的挑选"
   ;;
esac

在shell中,许多句子都有相应的完毕标志,比方if句子有fifor句子有donewhile句子有done等等。这些完毕标志的效果是用于标识句子的完毕位置,防止语法过错

三种循环

while循环

while循环用于在条件建立的情况下重复履行一段代码块

while [ condition ]
do
   command1
   command2
   ......
   commandN
done
#condition是需求判别的条件,command1到commandN是需求重复履行的指令或许代码块。每次履行完command1到commandN后,都会再次判别condition是否建立,假如建立则继续履行,不然退出循环

事例演示:

需求:从0加到10

#!/bin/bashsum=0
i=1
​
while [ $i -le 10 ]
do
  sum=$((sum + i))
  i=$((i + 1))
doneecho "1+2+3+...+10=$sum"

unitil循环

until循环与while循环相似,不同之处在于until循环在条件不建立的情况下重复履行一段代码块

until [ condition ]
do
   command1
   command2
   ......
   commandN
done#condition是需求判别的条件,command1到commandN是需求重复履行的指令或许代码块。每次履行完command1到commandN后,都会再次判别condition是否建立,假如不建立则继续履行,不然退出循环

事例演示:

一样是从0加到10

#!/bin/bashsum=0
i=1
​
until [ $i -gt 10 ]
do
  sum=$((sum + i))
  i=$((i + 1))
doneecho "1+2+3+...+10=$sum"

for循环

for循环用于遍历一组数据,并对每个数据履行相同的指令或许代码块

for variable in range
do
   command1
   command2
   ......
   commandN
done#variable是用于存储数据的变量名,range是需求遍历的数据规模,能够是数字、字符串、数组等。command1到commandN是需求重复履行的指令或许代码块,每次履行前,variable会被赋值为当时遍历的数据

事例演示:

遍历数组

运用for循环遍历数组array中的每个元素,并运用echo指令输出每个元素

#!/bin/bash
​
array=("apple" "banana" "orange" "watermelon")
​
for fruit in ${array[@]}
do
  echo $fruit
done
  • 除了遍历数组,for循环还能够遍历数字规模、文件列表等
#!/bin/bashsum=0
​
for i in {1..100}#或许运用视频事例中的for((i=0;i<10;i++))
do
  sum=$((sum + i))
doneecho "1+2+3+...+100=$sum"
  • 除了运用数字规模,for循环还能够运用通配符遍历文件列表
#!/bin/bashfor file in *.txt
do
  echo $file
done#运用for循环遍历当时目录下一切.txt文件,并运用echo指令输出每个文件的文件名

函数

在shell中,函数是一段能够重复运用的代码块,能够在脚本中界说并调用

function_name () {
   command1
   command2
   ......
   commandN
}
#function_name是函数名,command1到commandN是需求履行的指令或许代码块。界说完函数后,能够在脚本中经过函数名来调用函数

事例演示:

界说了一个名为hello的函数,函数的代码块中只需一条指令,用于输出“Hello, World!”。在界说完函数后,咱们在脚本中经过函数名hello来调用函数,从而输出“Hello, World!”

#!/bin/bashhello() {#除了这个语法之外,还有视频中的语法2:function hello(){}
  echo "Hello, World!"
}
​
hello
  • 在函数中,能够运用return句子来回来一个值

回来两数之和

#!/bin/bashadd() {
  sum=$(( $1 + $2 ))
   return $sum
}
​
add 3 5
result=$?
echo "3 + 5 = $result"#界说了一个名为`add`的函数,函数的代码块中核算了两个数之和,并运用`return`句子回来了这个和。在调用函数时,咱们传递了两个参数3和5,函数回来的值被存储到了变量`result`中,并运用`echo`指令输出了这个和

留意点

  • shell自上而下履行,函数必须在运用前界说
  • 函数获取变量和shell script相似,0代表函数名,后续参数经过0代表函数名,后续参数经过1、$2..获取
  • 函数内return只是表明函数履行状况,不代表函数履行成果
  • 回来成果一般运用echo、printf,在外面运用$()、“获取成果
  • 假如没有return,函数状况是上一条指令的履行状况,存储在$?中
function test() { # 界说一个名为test的函数
  local word="hello world" # 界说一个名为word的本地变量,值为"hello world"
 echo $word # 输出word的值到规范输出
  return 10 # 回来值为10
 unset word # 没有履行到这儿,因为前面现已履行了return句子
​
} # 函数界说完毕
​
content=`test` # 履行test函数,并将输出赋值给变量content
echo "状况码:$?" # 打印上一条指令的状况码,应该是10
echo "履行成果:$content" # 打印变量content的值,即"hello world"

模块化

模块化的原理是在当时shell内履行函数文件,方法:

  • source[函数库的途径]

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

模块化指令

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

  • 视频中检查日志的后10条内容:tail -n 10 cloundfun.log

  • 下图中这是一个Linux指令,用于检查文件的最终10行内容,其间:

    • tail是指令本身,表明显现文件尾部内容。
    • -n是一个选项,用于指定显现的行数。这儿指定为10,即显现文件的最终10行。
    • cloundfun.log是要显现内容的文件名,能够替换为其他文件的称号。

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

  • 与之前的指令相似,用于检查文件的最终10行内容,但是它还有一个 -f 选项,表明继续监视该文件的变化并实时输出新增加的内容,直到手动中止中止

    • -f选项:用于继续监视该文件的变化并实时输出新增加的内容。在排查问题的时分经常用到

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

履行进程和原理

  1. shell脚本一般以.sh结束,也能够没有,这是一个约定;榜首行需求指定用什么指令解说器来履行
#! /bin/bash
#! /user/bin/env bash
  1. 发动shell的三种方法
#文件名运转(子进程履行)
./filename.sh
​
​
#解说器运转(子进程履行)
bash ./filename.sh
​
​
# source运转(当时进程中履行)
source ./filename.sh

履行进程

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

  1. 字符解析

    • 辨认换行符、分号(;)做行的切割
    • 辨认指令衔接符(||&&管道)做指令的切割
    • 辨认空格、tab符,做指令和参数的切割
  2. shell打开,例如{1…3}解析为1 2 3

  3. 重定向,将stdin、stdout、stderr的文件描述符进行指向改变

  4. 履行指令

    • builtin直接履行
    • 非builtin运用$PATH查找,然后发动子进程履行
  5. 搜集状况并回来给脚本

shell打开

Shell 打开是指在履行指令之前,Shell 预处理指令行中的各种特别字符,将它们替换为实践的值或履行相应的操作

  1. 大括号打开(Brace Expansion):运用大括号 {} 将一组字符串包含在指令行中,Shell 将打开大括号内的一切字符串,并将其作为指令行的一部分。例如:echo file{1..3}.txt 将打开为 file1.txt file2.txt file3.txt
  2. 波涛号打开(Tilde Expansion):运用波涛号 ~ 将用户名或途径名包含在指令行中,Shell 将打开波涛号并将其替换为相应的用户名或途径名。例如:cd ~/Documents 将进入当时用户的 Documents 目录。
  3. 参数打开(Parameter Expansion):运用 $ 将变量名包含在指令行中,并运用一些特别符号来修正变量的值或进行字符串操作。例如:${var:-default} 表明假如变量 $var 未界说,则运用默许值 default
  4. 指令替换(Command Substitution):运用反引号或 $() 将一个指令包含起来,Shell 将履行该指令并将其输出作为指令行的一部分。例如:echo "The date is $(date)" 将输出当时日期和时刻。
  5. 数学核算(Arithmetic Expansion):运用 $(( )) 将一个算术表达式包含在指令行中,Shell 将核算该表达式并将其替换为核算成果。例如:echo $((1+2)) 将输出 3
  6. 文件名打开(Filename Expansion):运用通配符 *?[] 等来匹配文件名或途径名。Shell 将打开通配符并将其替换为匹配的文件名或途径名。例如:ls *.txt 将列出当时目录下一切扩展名为 .txt 的文件。

大括号打开

  • 一般由三部分构成,前缀、一对大括号、后缀,大括号内能够是逗号切割的字符串序列,也能够是序列表达式{x..y[..incr]}
#字符串序列
a(b,c,d)e => abe ace ade
​
#表达式序列,(数字能够运用incr调整增量,字母不行)
{1..5} => 1 2 3 4 5
​
{1..5..2} => 1 3 5
​
{a..e} => a b c d e

波涛号打开~

#当时用户主目录
~ => $HOME
​
~/fo => $HOME/foo
​
#指定用户的主目录
-fred/foo=>用户fred的SHOEM/foo
​
#当时作业目录
~+/foo => $PWD/foo
​
#上一个作业目录
~-/foo => ${$OLDPWD-'~-')/foo

参数打开

  1. 直接参数扩展${!parameter},其间引证的参数并不是parameter而是parameter的实践的值
parameter="var" # 界说一个名为 parameter 的变量,其值为字符串 "var"
var="hello" # 界说一个名为 var 的变量,其值为字符串 "hello"
echo ${!parameter} # 运用参数打开的方式,将变量 $parameter 的值 "var" 替换为 $var,从而得到变量 $var 的值 "hello",并将其输出到规范输出
​
#输出 hello
  1. 参数长度${#parameter}
  1. 空参数处理

    S{parameter:-word}#为空替换 {parameter:=word#为空替换,并将值赋给parameter变量 parameter:?word)#为空报错 {parameter:+word}#不为空替换

a=1 # 界说一个名为 a 的变量,其值为整数 1
​
echo ${a:-word} #1  # 输出变量 $a 的值,假如 $a 未界说或为空,则输出 "word"因为 $a 现已界说并赋值为 1,因而输出为 1
​
echo $(b:-word) #word  # 履行指令替换,履行指令 $b 并将其输出作为成果,假如 $b 未界说或为空,则输出 "word"因为 $b 未界说,因而输出为 "word"
​
echo $(par:=word) #word  # 履行指令替换,将变量 $par 的值设置为 "word",并将其输出作为成果因为 $par 未界说,因而输出为 "word"
​
echo $(par:-hello) #word  # 履行指令替换,输出变量 $par 的值,假如 $par 未界说或为空,则输出 "hello"因为 $par 未界说,因而输出为 "word"
​
echo $(par:+foo) #foo  # 履行指令替换,假如 $par 现已界说且非空,则输出 "foo",不然不输出任何内容因为 $par 未界说,因而不输出任何内容
​
#输出别离为:1 word word word foo
  1. 参数切片

    {parameter:offset) {parameter:offset:length}

  1. 参数部分删去

    {parameter%word} #最小限度从后边截取word {parameter%%word}#最大限度从后边截取word S{parameter#word}#最小限度从前面截取word ${parameter##word#最大限度从前面截取word

#!/bin/sh
​
str=abcdefg # 界说一个名为 str 的变量,其值为字符串 "abcdefg"
​
spl=$(str##*d) # 履行指令替换,删去变量 $str 最初到最终一个 "d" 之前的一切字符,并将剩下的字符串赋值给变量 $spl。因为变量 $str 的值为 "abcdefg",因而 $spl 的值为 "efg"。
# * 是通配符的一种,表明匹配恣意数量的恣意字符(包含 0 个字符)。具体来说,*d 表明匹配以字母 “d” 结束的字符串,并将匹配到的字符串删去。而 ## 表明从变量的最初开端匹配,删去最长的匹配项。
​
sp2=${str%%d*} # 履行参数打开,删去变量 $str 最终一个 "d" 以及之后的一切字符,并将剩下的字符串赋值给变量 $sp2。因为变量 $str 的值为 "abcdefg",因而 $sp2 的值为 "abc"。echo $spl #输出efg  # 输出变量 $spl 的值,即字符串 "efg"。echo $sp2 #输出abc  # 输出变量 $sp2 的值,即字符串 "abc"。# echo的两个输出别离如下:efg abc

指令替换

在子进程中履行指令,并用得到的成果替换包裹的内容,方式上有两种:$(…)或...

#! /bin/bashecho ${whoimi} # 输出变量 $whoimi 的值。因为 $whoimi 未界说,因而输出为空。foo(){ # 界说一个名为 foo 的函数
echo "asdasd" # 在函数中输出字符串 "asdasd"
}
​
a=`foo` # 履行指令替换,履行函数 foo 并将其输出作为成果,将成果赋值给变量 $a。因为函数 foo 的输出为 "asdasd",因而变量 $a 的值为 "asdasd"。

数学核算

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

#! /bin/bashecho $((1+2)) # 3

文件名打开

当有单词没有被引号包裹,且其间呈现了‘*’,‘?’,and ‘[’ 字符,则shell会去依照正则匹配的方法查找文件名进行替换,假如没找到则坚持不变

#! /bin/bash
​
$ echo D*
​
# 输出当时目录下一切以 D字母最初的目录、文件

调试和前端集成

调试的方法

  1. 一般log,运用echo、printf
  2. 运用set指令
  3. vscode debug插件
set装备 效果 弥补
-u 遇到不存在的变量就会报错,并中止履行。 -o nounset
-x 运转成果之前,先输出履行的那一行指令。 -o xtrace
-e 只需发生过错,就终止履行 -o errexit
-o pipefail 管道符链接的,只需一个子指令失利整个管道指令就失利,脚本就会终止履行。
#! /bin/bash#一般在最前面就进行装备
set -uxe -o pipefail
​
echo "hello world"

Vscode插件装备

  1. shellman:代码提示和主动补全

  2. shellcheck:代码语法校验

  3. shell-format:代码格局化

  4. Bash Debug:支撑单步调试

    • 装置vscode插件
    • 编写launch.json文件
    • 晋级bash到4.x以上版别

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

前端集成

  1. node中经过exec、spawn调用shell指令

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

  1. shell脚本中调用node指令

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

  1. 凭借zx等库进行javascript、shell script的融合

    • 凭借shell完结体系操作,文件io、内存、磁盘体系状况检查
    • 凭借nodejs完结应用层才能,网络io、核算等

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

最终的大纲

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