shell是一个命令行解释器,它接受应用程序/用户命令,然后调用操作系统内核。
如何理解上面这句话,在我们跟电脑中间,实际上不是直接进行交互的。电脑首先由硬件组成,再由内核组成,例如我们的Linux内核,在我们与其交互的时候,我们在内核外还有一层外核。例如Shell,我们通过外部的应用程序
与外核进行交互,然后才与内核交互。中间有一个转换的过程。
如下图:
Shell的特点:
那我们的shell是如何与Linux进行交互的呢?这时候就需要用到shell解析器,我们的Linux提供的shell解析器有几种,可通过:cat /etc/shells 查看
我们常用的是sh与bash。
bash与sh的关系
我们可以查看系统默认的解析器:
echo $SHELL
可以看到Centos默认的解析器是bash
当我们输入脚本的时候,系统如何知道我们输入的是什么呢?或者说它怎样知道该采取哪一种解析器呢?
这个时候我们就需要先进行指定。
脚本以**#!/bin/bash** 开头,也就是指定解析器。
我们用实例进行说明。
根据需求,我们可以采用以下方式:
这个时候我们已经完成了helloworld脚本的创建,并且已经在脚本中输入了打印helloworld的脚本。接下来需要执行这个脚本了,那么该如何执行呢?我们执行脚本的方式有以下几种。
这种方式不用赋予脚本+x权限。
这种情况必须得有可执行权限+x,这句话什么意思呢?举个例子,如果没有可执行权限+x的话,就会出现如下问题:
因此,需要首先赋予+x权限:
chmod +x helloworld.sh
【疑问】为什么第一种方式不需要权限,第二种需要呢?
第一种方式本质是bash解析器帮我们执行脚本,所以脚本本身不需要执行权限,而第二种执行方法,本质是脚本需要自己执行,因此需要执行权限。
先创建一个test.sh
分别用sh , bash , ./ , .四种方式来执行,查看区别:
前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则
子 shell 关闭,回到父 shell 中。
第三种,也就是使用在脚本路径前加“.”或者 source 的方式,可以使脚本内容在当前
shell 里执行,而无需打开子 shell!这也是为什么我们每次要修改完/etc/profile 文件以后,需
要 source 一下的原因。
开子 shell 与不开子 shell 的区别就在于,环境变量的继承关系,如在子 shell 中设置的
当前变量,父 shell 是不可见的。
shell变量可分为两类:局部变量和环境变量。局部变量只在创建它们的shell中可用。而环境变量则可以在创建它们的shell及其派生出来的任意子进程中使用。有些变量是用户创建的,其他的则是专用shell变量。
https://juejin.cn/post/7217994625343438906?searchId=2023081412335446C5833960E68BE7441B#heading-2
echo $HOME
(1) 定义变量:变量名=变量值,=号前后不能有空格
(2)撤销变量:unset变量名
(3)声明静态变量:readonly 变量,注意:不能 unset
(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建
议大写。
(2)等号两侧不能有空格
(3)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
(4)变量的值如果有空格,需要使用双引号或单引号括起来。
(1)定义变量X
(2)重新赋值
(3)撤销变量X
(4)声明静态的变量Y=2,静态变量不能unset
(5)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
(6)变量的值如果有空格,需要使用双引号或单引号括起来
(7)可把变量提升为全局环境变量,供其他Shell程序使用
如果报权限不够则执行: chmod +x helloworld.sh,增加执行权限,
helloworld.sh中的内容:
输出,发现Y并没有展示出来
进行变量提升,发现可以查看
可见以下实例:
基本语法:
parameter.sh文件写入以下:
执行
基本功能:
实例:
判断我们上面所展示parameter.sh脚本是否正确执行:
shell拥有多种运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符等。原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):
我们也可以采取以下方式来运行运算式:
(1)两个整数之间比较
注:如果是字符串之间的比较 ,用等号“=”判断相等;用“!=”判断不等。
(2)按照文件权限进行判断
(3)按照文件类型进行判断
(1)50是否大于40,如果为真,则返回0
(2)50是否大于60,如果为假,则返回1
(3)test.sh是否具有写权限,如果有,则返回0,否则返回1
(4)查看shells下,test.txt目录是否存在,如果存在,则返回0,否则返回1
(5)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一
条命令执行失败后,才执行下一条命令)
基本语法
//方式一
if [ 条件判断式 ] ;then
程序
fi
//方式二:
if [ 条件判断式 ]
then
程序
fi
注意:
①[ 条件判断式 ],中括号和条件判断式之间必须有空格
②if 后要有空格
实例:
执行查看结果:
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
实例:
输出结果:
基本语法:
case $变量名 in
"值 1")
如果变量的值等于值 1,则执行程序 1
;;
"值 2")
如果变量的值等于值 2,则执行程序 2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
//(1)case 行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
//(2)双分号“;;”表示命令序列结束,相当于 java 中的 break。
//(3)最后的“*)”表示默认模式,相当于 java 中的 default。
实例:
输入一个数字,如果是 1,则输出 哈哈哈哈,如果是 2,则输出 呵呵呵呵,如果是其它,输出
嘻嘻嘻嘻。
执行结果:
基本语句1:
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
实例:
从1加到100
上面i应为i<=100
执行结果:
基本语法 2:
for 变量 in 值 1 值 2 值 3…
do
程序
done
实例:
打印参数:
执行结果:
基本语法:
while [ 条件判断式 ]
do
程序
done
实例:
从1加到100:
执行结果:
基本语法:
read (选项) (参数)
①选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
②参数
变量:指定读取值的变量名
实例:
提示10s内,读取控制台输入的名称:
执行结果:
shell一个非常重要的特性是它可作为一种编程语言来使用。因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释。而程序的加载和解释都是非常耗时的。 针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。shell还以一种内部格式来存放这些函数,这样就不必耗费大量的时间来解释它们。
——百度百科
basename [string / pathname] [suffix]
选项:
suffix 为后缀,如果 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉。
实例:
截取该basename /home/scripts/test0821.txt路径的文件名称
dirname 文件绝对路径
实例:
获取 test0821.txt 文件的路径
基本语法:
[ function ] funname[()]
{
Action;
[return int;]
}
【注意】
(1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n,n的范围是0-255。
实例:
计算两个参数的和:
执行结果: