1.shell的概念
shell是一个命令行解释器,它接受应用程序/用户命令,然后调用操作系统内核。
如何理解上面这句话,在我们跟电脑中间,实际上不是直接进行交互的。电脑首先由硬件组成,再由内核组成,例如我们的Linux内核,在我们与其交互的时候,我们在内核外还有一层外核。例如Shell,我们通过外部的应用程序
与外核进行交互,然后才与内核交互。中间有一个转换的过程。
如下图:
Shell的特点:
- 功能强大
- 易编写
- 易调试
- 灵活性强
那我们的shell是如何与Linux进行交互的呢?这时候就需要用到shell解析器,我们的Linux提供的shell解析器有几种,可通过:cat /etc/shells 查看
我们常用的是sh与bash。
bash与sh的关系
- /bin/sh:一个老牌 shell,一般情况下,也是系统的默认 shell。
- /bin/bash: 在 sh 的基础上增加了一些实用特性,是使用最广泛的 shell。
我们可以查看系统默认的解析器:
echo $SHELL
可以看到Centos默认的解析器是bash
2.shell脚本
当我们输入脚本的时候,系统如何知道我们输入的是什么呢?或者说它怎样知道该采取哪一种解析器呢?
这个时候我们就需要先进行指定。
2.1 脚本格式
脚本以**#!/bin/bash** 开头,也就是指定解析器。
2.2 经典helloworld
我们用实例进行说明。
- 实例需求:创建一个shell脚本,输出helloworld
根据需求,我们可以采用以下方式:
- touch helloworld.sh创建
- vim helloworld.sh 进行插入
- 插入完成,esc退出,然后**:wq**进行保存
这个时候我们已经完成了helloworld脚本的创建,并且已经在脚本中输入了打印helloworld的脚本。接下来需要执行这个脚本了,那么该如何执行呢?我们执行脚本的方式有以下几种。
2.3 执行脚本的方式
2.3.1 采用bash或sh+脚本的相对路径或绝对路径
这种方式不用赋予脚本+x权限。
- sh+脚本的相对路径
- sh+脚本的绝对路径
- bash+脚本相对路径
- bash+脚本绝对路径
2.3.2 采用输入脚本的绝对路径或相对路径执行脚本
这种情况必须得有可执行权限+x,这句话什么意思呢?举个例子,如果没有可执行权限+x的话,就会出现如下问题:
- 相对路径
因此,需要首先赋予+x权限:
chmod +x helloworld.sh
- 绝对路径
【疑问】为什么第一种方式不需要权限,第二种需要呢?
第一种方式本质是bash解析器帮我们执行脚本,所以脚本本身不需要执行权限,而第二种执行方法,本质是脚本需要自己执行,因此需要执行权限。
2.3.3 在脚本的路径前加上“.”或source
先创建一个test.sh
分别用sh , bash , ./ , .四种方式来执行,查看区别:
前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则
子 shell 关闭,回到父 shell 中。
第三种,也就是使用在脚本路径前加“.”或者 source 的方式,可以使脚本内容在当前
shell 里执行,而无需打开子 shell!这也是为什么我们每次要修改完/etc/profile 文件以后,需
要 source 一下的原因。
开子 shell 与不开子 shell 的区别就在于,环境变量的继承关系,如在子 shell 中设置的
当前变量,父 shell 是不可见的。
3.变量
shell变量可分为两类:局部变量和环境变量。局部变量只在创建它们的shell中可用。而环境变量则可以在创建它们的shell及其派生出来的任意子进程中使用。有些变量是用户创建的,其他的则是专用shell变量。
https://juejin.cn/post/7217994625343438906?searchId=2023081412335446C5833960E68BE7441B#heading-2
3.1变量指定规则
- 变量名必须以字母或下划线字符开头。其余的字符可以是字母、数字(0~9)或下划线字符。任何其他的字符都标志着变量名的终止。名字是大小写敏感的。给变量赋值时,等号周围不能有任何空白符。为了给变量赋空值,可以在等号后跟一个换行符。用set命令可以查看所有的变量,unset var命令可以清除变量var,var相当于没有定义过。readonly var可以把var变为只读变量,定义之后不能对var进行任何更改。对shell变量的引用方式很多,用这些方式可以方便的获取shell变量的值,变量值的长度,变量的一个字串,变量被部分替换后的值等等。
3.2 变量的分类
- 环境变量(Environment Variable):环境变量是在Shell启动时由操作系统设置的,它们对于所有的Shell和Shell执行的程序都是可见的。一些常见的环境变量包括PATH、HOME、USER等。
- 本地变量(Local Variable):本地变量是由Shell程序定义的,仅在当前Shell会话中可见,对于其他的Shell和Shell执行的程序是不可见的。本地变量可以通过=符号来定义和赋值,例如myvar=“hello”。
- 位置参数变量(Positional Parameter Variable):位置参数变量是用来存储Shell脚本的命令行参数的,它们包括$1、$2、$3等。例如,如果我们运行一个Shell脚本并且传递了两个参数,那么这两个参数会被分别赋值给$1和$2。
- 特殊变量(Special Variable):特殊变量是由Shell程序预定义的,用于存储一些特定的值或状态。例如,
?
用于存储上一个命令的返回值,
? 用于存储上一个命令的返回值,
?用于存储上一个命令的返回值,
用于存储当前
S
h
e
l
l
进程的
P
I
D
,
用于存储当前Shell进程的PID,
用于存储当前Shell进程的PID,IFS用于存储当前Shell的字段分隔符等。
3.3 系统预定义变量
3.3.1 常用系统变量
- H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER等
- 如何查看系统变量的值
echo $HOME
- 显示当前Shell中所有变量,采用set
3.4 自定义变量
3.4.1基本语法
(1) 定义变量:变量名=变量值,=号前后不能有空格
(2)撤销变量:unset变量名
(3)声明静态变量:readonly 变量,注意:不能 unset
3.4.2 变量定义规则
(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建
议大写。
(2)等号两侧不能有空格
(3)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
(4)变量的值如果有空格,需要使用双引号或单引号括起来。
3.4.3 实例
(1)定义变量X
(2)重新赋值
(3)撤销变量X
(4)声明静态的变量Y=2,静态变量不能unset
(5)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
(6)变量的值如果有空格,需要使用双引号或单引号括起来
(7)可把变量提升为全局环境变量,供其他Shell程序使用
如果报权限不够则执行: chmod +x helloworld.sh,增加执行权限,
helloworld.sh中的内容:
输出,发现Y并没有展示出来
进行变量提升,发现可以查看
3.5 特殊变量
3.5.1 $n
- $n,n为数字,$0 代表该脚本名称,$1- 9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10})。如下图实例:
3.5.2$#
- 基本语法:$#,获取输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性。
可见以下实例:
3.5.3 ∗ 、 *、 ∗、@
基本语法:
- ∗ 这个变量代表命令行中所有的参数, * 这个变量代表命令行中所有的参数, ∗这个变量代表命令行中所有的参数,*把所有的参数看成一个整体
- @ 这个变量也代表命令行中所有的参数,不过 @ 这个变量也代表命令行中所有的参数,不过 @这个变量也代表命令行中所有的参数,不过@把每个参数区分对待
parameter.sh文件写入以下:
执行
2.5.4**$?**
基本功能:
- 最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一 个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
实例:
判断我们上面所展示parameter.sh脚本是否正确执行:
3.6常见变量汇总
- $$:当前脚本或进程的进程ID。
- $?:上一个命令或脚本的退出状态码。
- $!:上一个后台进程的进程ID。
- $USER:当前用户的用户名。
- $HOME:当前用户的主目录路径。
- $PATH:当前系统的执行路径。
- $PWD:当前工作目录路径。
- $SHELL:当前使用的Shell程序路径。
- $RANDOM:一个0到32767之间的随机数。
- $LINENO:当前脚本的行号。
- $IFS:当前脚本的字段分隔符。
- $PS1:Shell提示符的格式。
- $PS2:Shell续行提示符的格式。
4.运算符
shell拥有多种运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符等。原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
- expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):
我们也可以采取以下方式来运行运算式:
- $( (运算式))
- [ 运算式 ] 。运算式要放在方括号之间,并且要有空格,例如 : [ [ 运算式 ]。运算式要放在方括号之间,并且要有空格,例如: [ [运算式]。运算式要放在方括号之间,并且要有空格,例如:[a==$b] 是错误的,必须写成 [ $a == $b ]。
5.条件判断
5.1基本语法:
- test condition
- [ condition ] , 注意condition前后有空格
5.2常用判断条件
(1)两个整数之间比较
- -eq 等于(equal)
- -ne 不等于(not equal)
- -lt 小于(less than)
- -le 小于等于(less equal)
- -gt 大于(greater than)
- -ge 大于等于(greater equal)
注:如果是字符串之间的比较 ,用等号“=”判断相等;用“!=”判断不等。
(2)按照文件权限进行判断
- -r 有读的权限(read)
- -w 有写的权限(write)
- -x 有执行的权限(execute)
(3)按照文件类型进行判断
- -e 文件存在(existence)
- -f 文件存在并且是一个常规的文件(file)
- -d 文件存在并且是一个目录(directory)
5.3案例
(1)50是否大于40,如果为真,则返回0
(2)50是否大于60,如果为假,则返回1
(3)test.sh是否具有写权限,如果有,则返回0,否则返回1
(4)查看shells下,test.txt目录是否存在,如果存在,则返回0,否则返回1
(5)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一
条命令执行失败后,才执行下一条命令)
6.流程控制
6.1if判断
6.1.1单分支
基本语法
//方式一
if [ 条件判断式 ] ;then
程序
fi
//方式二:
if [ 条件判断式 ]
then
程序
fi
注意:
①[ 条件判断式 ],中括号和条件判断式之间必须有空格
②if 后要有空格
实例:
执行查看结果:
6.1.2多分支
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
实例:
输出结果:
6.2case语句
基本语法:
case $变量名 in
"值 1")
如果变量的值等于值 1,则执行程序 1
;;
"值 2")
如果变量的值等于值 2,则执行程序 2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
//(1)case 行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
//(2)双分号“;;”表示命令序列结束,相当于 java 中的 break。
//(3)最后的“*)”表示默认模式,相当于 java 中的 default。
实例:
输入一个数字,如果是 1,则输出 哈哈哈哈,如果是 2,则输出 呵呵呵呵,如果是其它,输出
嘻嘻嘻嘻。
执行结果:
6.3for循环
基本语句1:
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
实例:
从1加到100
上面i应为i<=100
执行结果:
基本语法 2:
for 变量 in 值 1 值 2 值 3…
do
程序
done
实例:
打印参数:
执行结果:
6.4while循环
基本语法:
while [ 条件判断式 ]
do
程序
done
实例:
从1加到100:
执行结果:
7.read读取控制台输入
基本语法:
read (选项) (参数)
①选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
②参数
变量:指定读取值的变量名
实例:
提示10s内,读取控制台输入的名称:
执行结果:
8.函数
shell一个非常重要的特性是它可作为一种编程语言来使用。因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释。而程序的加载和解释都是非常耗时的。 针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。shell还以一种内部格式来存放这些函数,这样就不必耗费大量的时间来解释它们。
——百度百科
8.1系统函数
8.1.1basename
- 基本语法:
basename [string / pathname] [suffix]
- 功能描述:basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。basename 可以理解为取路径里的文件名称
选项:
suffix 为后缀,如果 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉。
实例:
截取该basename /home/scripts/test0821.txt路径的文件名称
8.1.2dirname
- 基本语法:
dirname 文件绝对路径
- 功能描述:从给定的包含绝对路径的文件名中去除文件名 (非目录的部分),然后返回剩下的路径(目录的部分),dirname 可以理解为取文件路径的绝对路径名称
实例:
获取 test0821.txt 文件的路径
8.2自定义函数
基本语法:
[ function ] funname[()]
{
Action;
[return int;]
}
【注意】
(1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n,n的范围是0-255。
实例:
计算两个参数的和:文章来源:https://www.toymoban.com/news/detail-781062.html
执行结果:文章来源地址https://www.toymoban.com/news/detail-781062.html
到了这里,关于Shell扫盲版——建议收藏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!