Shell扫盲版——建议收藏

发布时间:2024年01月11日

1.shell的概念

shell是一个命令行解释器,它接受应用程序/用户命令,然后调用操作系统内核。

如何理解上面这句话,在我们跟电脑中间,实际上不是直接进行交互的。电脑首先由硬件组成,再由内核组成,例如我们的Linux内核,在我们与其交互的时候,我们在内核外还有一层外核。例如Shell,我们通过外部的应用程序
与外核进行交互,然后才与内核交互。中间有一个转换的过程。
如下图:
image.png
Shell的特点:

  • 功能强大
  • 易编写
  • 易调试
  • 灵活性强

那我们的shell是如何与Linux进行交互的呢?这时候就需要用到shell解析器,我们的Linux提供的shell解析器有几种,可通过:cat /etc/shells 查看
image.png

我们常用的是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

根据需求,我们可以采用以下方式:

  1. touch helloworld.sh创建
  2. vim helloworld.sh 进行插入
  3. 插入完成,esc退出,然后**:wq**进行保存

image.png

这个时候我们已经完成了helloworld脚本的创建,并且已经在脚本中输入了打印helloworld的脚本。接下来需要执行这个脚本了,那么该如何执行呢?我们执行脚本的方式有以下几种。

2.3 执行脚本的方式

2.3.1 采用bash或sh+脚本的相对路径或绝对路径

这种方式不用赋予脚本+x权限。

  • sh+脚本的相对路径

image.png

  • sh+脚本的绝对路径

image.png

  • bash+脚本相对路径

image.png

  • bash+脚本绝对路径

image.png

2.3.2 采用输入脚本的绝对路径或相对路径执行脚本

这种情况必须得有可执行权限+x,这句话什么意思呢?举个例子,如果没有可执行权限+x的话,就会出现如下问题:

  • 相对路径

image.png
因此,需要首先赋予+x权限:

chmod +x helloworld.sh

image.png

  • 绝对路径

image.png

【疑问】为什么第一种方式不需要权限,第二种需要呢?

第一种方式本质是bash解析器帮我们执行脚本,所以脚本本身不需要执行权限,而第二种执行方法,本质是脚本需要自己执行,因此需要执行权限。

2.3.3 在脚本的路径前加上“.”或source

先创建一个test.sh
image.png
分别用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进程的PIDIFS用于存储当前Shell的字段分隔符等。


3.3 系统预定义变量

3.3.1 常用系统变量

  • H O M E 、 HOME、 HOMEPWD、 S H E L L 、 SHELL、 SHELLUSER等
  1. 如何查看系统变量的值
echo $HOME

image.png

  1. 显示当前Shell中所有变量,采用set

image.png

3.4 自定义变量

3.4.1基本语法

(1) 定义变量:变量名=变量值,=号前后不能有空格
(2)撤销变量:unset变量名
(3)声明静态变量:readonly 变量,注意:不能 unset

3.4.2 变量定义规则

(1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建
议大写。
(2)等号两侧不能有空格
(3)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
(4)变量的值如果有空格,需要使用双引号或单引号括起来。

3.4.3 实例

(1)定义变量X
image.png
(2)重新赋值
image.png
(3)撤销变量X
image.png
(4)声明静态的变量Y=2,静态变量不能unset
image.png
(5)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
image.png
(6)变量的值如果有空格,需要使用双引号或单引号括起来
image.png
(7)可把变量提升为全局环境变量,供其他Shell程序使用
如果报权限不够则执行: chmod +x helloworld.sh,增加执行权限,
helloworld.sh中的内容:
image.png
输出,发现Y并没有展示出来
image.png
进行变量提升,发现可以查看
image.png

3.5 特殊变量

3.5.1 $n

  • $n,n为数字,$0 代表该脚本名称,$1- 9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如 9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10})。如下图实例:

image.png
image.png

3.5.2$#

  • 基本语法:$#,获取输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性。

可见以下实例:
image.png

image.png

3.5.3 ? 、 *、 ?@

基本语法:

  • ? 这个变量代表命令行中所有的参数, * 这个变量代表命令行中所有的参数, ?这个变量代表命令行中所有的参数,*把所有的参数看成一个整体
  • @ 这个变量也代表命令行中所有的参数,不过 @ 这个变量也代表命令行中所有的参数,不过 @这个变量也代表命令行中所有的参数,不过@把每个参数区分对待

parameter.sh文件写入以下:
image.png
执行
image.png

2.5.4**$?**

基本功能:

  • 最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一 个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。

实例:
判断我们上面所展示parameter.sh脚本是否正确执行:
image.png

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 是一款表达式计算工具,使用它能完成表达式的求值操作。

例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):

image.png

我们也可以采取以下方式来运行运算式:

  • $( (运算式))
  • [ 运算式 ] 。运算式要放在方括号之间,并且要有空格,例如 : [ [ 运算式 ]。运算式要放在方括号之间,并且要有空格,例如: [ [运算式]。运算式要放在方括号之间,并且要有空格,例如:[a==$b] 是错误的,必须写成 [ $a == $b ]。

image.png

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
image.png

(2)50是否大于60,如果为假,则返回1
image.png

(3)test.sh是否具有写权限,如果有,则返回0,否则返回1
image.png

(4)查看shells下,test.txt目录是否存在,如果存在,则返回0,否则返回1
image.png

(5)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一
条命令执行失败后,才执行下一条命令)
image.png

6.流程控制

6.1if判断

6.1.1单分支

基本语法

//方式一
if [ 条件判断式 ] ;then
	程序
fi

//方式二:
if [ 条件判断式 ]
then
	程序
fi

注意:
①[ 条件判断式 ],中括号和条件判断式之间必须有空格
②if 后要有空格

实例:
image.png
执行查看结果:
image.png

6.1.2多分支

if [ 条件判断式 ] 
then 
	程序 
elif [ 条件判断式 ] 
then 
	程序 
else 
	程序 
fi

实例:
image.png
输出结果:
image.png

6.2case语句

基本语法:

case $变量名 in 
"值 1") 
	如果变量的值等于值 1,则执行程序 1 
;; 
"值 2") 
	如果变量的值等于值 2,则执行程序 2 
;; 
…省略其他分支… 
*) 
	如果变量的值都不是以上的值,则执行此程序 
;; 
esac

//(1)case 行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
//(2)双分号“;;”表示命令序列结束,相当于 java 中的 break。
//(3)最后的“*)”表示默认模式,相当于 java 中的 default。

实例:
输入一个数字,如果是 1,则输出 哈哈哈哈,如果是 2,则输出 呵呵呵呵,如果是其它,输出
嘻嘻嘻嘻。
image.png
执行结果:
image.png

6.3for循环

基本语句1:

for (( 初始值;循环控制条件;变量变化 )) 
do 
	程序 
done

实例:
从1加到100
image.png
上面i应为i<=100
执行结果:
image.png
基本语法 2:

for 变量 in 值 1 值 2 值 3… 
do 
	程序 
done

实例:
打印参数:
image.png
执行结果:
image.png

6.4while循环

基本语法:

while [ 条件判断式 ] 
do 
	程序 
done

实例:
从1加到100:
image.png
执行结果:
image.png

7.read读取控制台输入

基本语法:
read (选项) (参数)
①选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
②参数
变量:指定读取值的变量名

实例:
提示10s内,读取控制台输入的名称:
image.png
执行结果:
image.png

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路径的文件名称
image.png

8.1.2dirname

  • 基本语法:

dirname 文件绝对路径

  • 功能描述:从给定的包含绝对路径的文件名中去除文件名 (非目录的部分),然后返回剩下的路径(目录的部分),dirname 可以理解为取文件路径的绝对路径名称

实例:
获取 test0821.txt 文件的路径
image.png

8.2自定义函数

基本语法:

[ function ] funname[()] 
{ 
  Action; 
  [return int;] 
}

【注意】
(1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n,n的范围是0-255。

实例:
计算两个参数的和:
image.png

执行结果:
image.png

文章来源:https://blog.csdn.net/weixin_46913665/article/details/135533250
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。