学习shell的价值:
- Linux服务器的基本操作和办理
- 前端Node.js服务的进程办理、问题排查、资源监控等运维操作
- 运用shell编写TCE、SCM、Docker脚本,完结服务编译和部署
课程准备
- 一台装置了 linux 体系的物理机或许云主机,可运转 shell 脚本
- 本地的 vscode 装置 Bash Debug 插件,并晋级 bash 到4.x以上
- Npm 大局装置 zx 依赖
Shell基本概念
概念
Shell(也称为指令行界面或终端)是一种经过文本输入和输出进行交互的核算机用户界面。它答应用户经过输入指令来履行操作、运转程序和办理体系
- 指令(Command):Shell经过输入指令来履行不同的操作或使命,例如创立文件、仿制文件、移动文件、运转程序等。指令通常由指令名和参数组成,指令名指定要履行的操作,参数用于指定指令的具体操作方法或效果目标。
- 提示符(Prompt):Shell在等待用户输入指令时会显现一个提示符,通常是一个特别的字符或字符串,表明Shell现已准备好接受指令输入。
- 文件体系(File System):Shell能够用于办理核算机上的文件和目录,包含创立、仿制、移动、删去、重命名、检查等操作。Shell运用文件体系的途径来定位文件和目录,例如绝对途径(从根目录开端的完整途径)和相对途径(从当时目录开端的相对途径)。
- 管道(Pipeline):Shell答应将多个指令经过管道衔接起来,其间一个指令的输出作为另一个指令的输入。这样能够完结多个指令的组合和协作,从而愈加灵敏地完结杂乱的使命。
- 环境变量(Environment Variable):Shell运用环境变量来存储体系级别的装备信息、用户装备和运转时参数。环境变量能够在指令中运用,并且能够经过设置和修正来影响Shell的行为和操作。
- 脚本(Script):Shell答应用户编写一系列指令的脚本文件,以便将一组指令作为一个单独的程序运转。脚本能够包含条件句子、循环、函数等控制结构,从而完结愈加杂乱的主动化使命。
- 快捷键(Shortcut):Shell供给了许多快捷键和指令行修正功能,用于提高指令行操作的功率和快捷性。例如,能够运用上下箭头键来阅读前史指令,运用Tab键进行指令和文件名的主动补全,运用Ctrl+C来中止正在履行的指令等。
- Shell
`和
Bash`能够理解为类和实例的联系
Bash的进程
以下内容当作课外内容弥补(当故事看都行):
- 1989年:Bash由布莱恩福克斯(Brian Fox)开发,并初次发布。Bash基于Bourne Shell(sh),是Bourne Shell的一种改善版别,它增加了许多新的特性,例如指令前史、指令行修正、作业控制等。
- 1993年:Bash 1.12发布,这是Bash的榜首个公开发布版别。Bash开端在Unix和Linux体系中广泛传播,并成为默许的指令行Shell。
- 1994年:Bash 2.0发布,引入了更多的新特性,包含指令别号、条件句子、循环、函数、算术运算等,使Bash变得愈加强壮和灵敏。
- 2000年:Bash 2.05b发布,这是一个重要的版别,引入了许多新的特性,包含指令补全、目录堆栈、指令行参数处理等,进一步提升了Bash的用户友好性和交互性。
- 2007年:Bash 3.0发布,引入了更多的新特性,包含新的扩展特点、数组、相关数组等,使Bash愈加适用于杂乱的脚本编程和体系办理使命。
- 2011年:Bash 4.2发布,带来了许多新的特性和改善,包含新的内置指令、更强壮的方式匹配、更灵敏的前史指令办理、更高效的作业控制等。
- 2016年:Bash 4.4发布,带来了许多新的特性和改善,包含新的参数扩展、新的运算符、更好的过错处理、更强壮的指令前史办理等。
- 2019年:Bash 5.0发布,引入了一些新特性,例如新的管道重定向符号、新的内置指令、新的变量扩展和运算符等,继续改善和增强了Bash的功能和功能。
构成
Unix shell既是一个指令解说器也是一种编程语言。作为指令解说器,shell为丰富的GNU东西集供给了用户接口。
指令和语法
类型 | 效果域 | 声明方法 | 规范 |
---|---|---|---|
自界说变量 | 当时shell | =(隐式声明) | 字符串、整型、浮点型、日期型 |
环境变量 | 当时shell及其子shell | export declare -x(显现声明) | |
体系环境变量 | 一切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:[新增途径] |
-
$#
表明当时脚本或函数的参数个数。在shell脚本中,能够经过$#
来获取当时脚本或函数的参数个数,并依据参数个数履行相应的操作。 -
$*
表明当时脚本或函数的一切参数列表。在shell脚本中,能够经过$*
来获取当时脚本或函数的一切参数,并依据参数列表履行相应的操作。 -
$?
表明上一个指令的退出状况码。在shell脚本中,能够经过$?
来获取上一个指令的退出状况码,并依据状况码履行相应的操作。 -
$PS1
表明shell提示符的格局。在shell中,能够经过修正$PS1
来自界说shell提示符的格局,以习惯个人习惯或需求。 -
$HOME
表明当时用户的主目录。在shell脚本中,能够经过$HOME
来获取当时用户的主目录,并依据主目录履行相应的操作。 -
$PATH
表明体系的可履行文件途径列表。在shell中,能够经过修正$PATH
来增加或删去体系的可履行文件途径,以便更方便地履行体系指令或自界说指令。
装备文件加载
运算符和引证
管道
管道与管道符 | ,效果是将前一个指令的成果传递给后边的指令 语法: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
重定向
- 修正了默许的联系
-
>
:将指令的输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则掩盖。 -
>>
:将指令的输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则在文件末尾追加。 -
2>
:将指令的过错输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则掩盖。 -
&>
:将指令的输出和过错输出重定向到一个文件中,假如文件不存在则创立,假如文件现已存在则掩盖。 -
<
:将一个文件的内容作为指令的输入。 -
<<
:将一段字符串作为指令的输入。
以下是一些比方:
-
ls > file.txt
:将ls
指令的输出重定向到file.txt
文件中,假如文件不存在则创立,假如文件现已存在则掩盖。 -
ls >> file.txt
:将ls
指令的输出重定向到file.txt
文件中,假如文件不存在则创立,假如文件现已存在则在文件末尾追加。 -
ls 2> error.txt
:将ls
指令的过错输出重定向到error.txt
文件中,假如文件不存在则创立,假如文件现已存在则掩盖。 -
ls &> output.txt
:将ls
指令的输出和过错输出重定向到output.txt
文件中,假如文件不存在则创立,假如文件现已存在则掩盖。 -
sort < file.txt
:将file.txt
文件的内容作为sort
指令的输入。 -
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中,分支句子主要有if句子和case句子。
- 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/bash
echo "请输入一个整数:"
read num
if [ $((num % 2)) -eq 0 ]
then
echo "$num 是偶数"
else
echo "$num 是奇数"
fi
-
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/bash
echo "请挑选一个操作:"
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
句子有fi
,for
句子有done
,while
句子有done
等等。这些完毕标志的效果是用于标识句子的完毕位置,防止语法过错
三种循环
while循环
while
循环用于在条件建立的情况下重复履行一段代码块
while [ condition ]
do
command1
command2
......
commandN
done
#condition是需求判别的条件,command1到commandN是需求重复履行的指令或许代码块。每次履行完command1到commandN后,都会再次判别condition是否建立,假如建立则继续履行,不然退出循环
事例演示:
需求:从0加到10
#!/bin/bash
sum=0
i=1
while [ $i -le 10 ]
do
sum=$((sum + i))
i=$((i + 1))
done
echo "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/bash
sum=0
i=1
until [ $i -gt 10 ]
do
sum=$((sum + i))
i=$((i + 1))
done
echo "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/bash
sum=0
for i in {1..100}#或许运用视频事例中的for((i=0;i<10;i++))
do
sum=$((sum + i))
done
echo "1+2+3+...+100=$sum"
- 除了运用数字规模,
for
循环还能够运用通配符遍历文件列表
#!/bin/bash
for 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/bash
hello() {#除了这个语法之外,还有视频中的语法2:function hello(){}
echo "Hello, World!"
}
hello
- 在函数中,能够运用
return
句子来回来一个值
回来两数之和
#!/bin/bash
add() {
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[函数库的途径]
模块化指令
-
视频中检查日志的后10条内容:
tail -n 10 cloundfun.log
-
下图中这是一个Linux指令,用于检查文件的最终10行内容,其间:
-
tail
是指令本身,表明显现文件尾部内容。 -
-n
是一个选项,用于指定显现的行数。这儿指定为10,即显现文件的最终10行。 -
cloundfun.log
是要显现内容的文件名,能够替换为其他文件的称号。
-
-
与之前的指令相似,用于检查文件的最终10行内容,但是它还有一个
-f
选项,表明继续监视该文件的变化并实时输出新增加的内容,直到手动中止中止-
-f
选项:用于继续监视该文件的变化并实时输出新增加的内容。在排查问题的时分经常用到
-
履行进程和原理
- shell脚本一般以.sh结束,也能够没有,这是一个约定;榜首行需求指定用什么指令解说器来履行
#! /bin/bash
#! /user/bin/env bash
- 发动shell的三种方法
#文件名运转(子进程履行)
./filename.sh
#解说器运转(子进程履行)
bash ./filename.sh
# source运转(当时进程中履行)
source ./filename.sh
履行进程
-
字符解析
- 辨认换行符、分号(;)做行的切割
- 辨认指令衔接符(||&&管道)做指令的切割
- 辨认空格、tab符,做指令和参数的切割
-
shell打开,例如{1…3}解析为1 2 3
-
重定向,将stdin、stdout、stderr的文件描述符进行指向改变
-
履行指令
- builtin直接履行
- 非builtin运用$PATH查找,然后发动子进程履行
-
搜集状况并回来给脚本
shell打开
Shell 打开是指在履行指令之前,Shell 预处理指令行中的各种特别字符,将它们替换为实践的值或履行相应的操作
- 大括号打开(Brace Expansion):运用大括号
{}
将一组字符串包含在指令行中,Shell 将打开大括号内的一切字符串,并将其作为指令行的一部分。例如:echo file{1..3}.txt
将打开为file1.txt file2.txt file3.txt
。 - 波涛号打开(Tilde Expansion):运用波涛号
~
将用户名或途径名包含在指令行中,Shell 将打开波涛号并将其替换为相应的用户名或途径名。例如:cd ~/Documents
将进入当时用户的 Documents 目录。 - 参数打开(Parameter Expansion):运用
$
将变量名包含在指令行中,并运用一些特别符号来修正变量的值或进行字符串操作。例如:${var:-default}
表明假如变量$var
未界说,则运用默许值default
。 - 指令替换(Command Substitution):运用反引号或
$()
将一个指令包含起来,Shell 将履行该指令并将其输出作为指令行的一部分。例如:echo "The date is $(date)"
将输出当时日期和时刻。 - 数学核算(Arithmetic Expansion):运用
$(( ))
将一个算术表达式包含在指令行中,Shell 将核算该表达式并将其替换为核算成果。例如:echo $((1+2))
将输出3
。 - 文件名打开(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
参数打开
- 直接参数扩展${!parameter},其间引证的参数并不是parameter而是parameter的实践的值
parameter="var" # 界说一个名为 parameter 的变量,其值为字符串 "var"
var="hello" # 界说一个名为 var 的变量,其值为字符串 "hello"
echo ${!parameter} # 运用参数打开的方式,将变量 $parameter 的值 "var" 替换为 $var,从而得到变量 $var 的值 "hello",并将其输出到规范输出
#输出 hello
- 参数长度${#parameter}
-
空参数处理
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
-
参数切片
{parameter:offset) {parameter:offset:length}
-
参数部分删去
{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/bash
echo ${whoimi} # 输出变量 $whoimi 的值。因为 $whoimi 未界说,因而输出为空。
foo(){ # 界说一个名为 foo 的函数
echo "asdasd" # 在函数中输出字符串 "asdasd"
}
a=`foo` # 履行指令替换,履行函数 foo 并将其输出作为成果,将成果赋值给变量 $a。因为函数 foo 的输出为 "asdasd",因而变量 $a 的值为 "asdasd"。
数学核算
运用$( ( ) ) 包裹数学运算表达式,得到成果并替换
#! /bin/bash
echo $((1+2)) # 3
文件名打开
当有单词没有被引号包裹,且其间呈现了‘*’,‘?’,and ‘[’ 字符,则shell会去依照正则匹配的方法查找文件名进行替换,假如没找到则坚持不变
#! /bin/bash
$ echo D*
# 输出当时目录下一切以 D字母最初的目录、文件
调试和前端集成
调试的方法
- 一般log,运用echo、printf
- 运用set指令
- vscode debug插件
set装备 | 效果 | 弥补 |
---|---|---|
-u | 遇到不存在的变量就会报错,并中止履行。 | -o nounset |
-x | 运转成果之前,先输出履行的那一行指令。 | -o xtrace |
-e | 只需发生过错,就终止履行 | -o errexit |
-o pipefail | 管道符链接的,只需一个子指令失利整个管道指令就失利,脚本就会终止履行。 |
#! /bin/bash
#一般在最前面就进行装备
set -uxe -o pipefail
echo "hello world"
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、核算等
最终的大纲