Skip to content

啥是Shell

Linux 系统结构的本质:

  1. Linux 内核(Kernel)
    • 是操作系统的核心。
    • 负责硬件管理内存调度文件系统访问进程控制等。
  2. Shell(壳)
    • 是一个应用程序(如 bashzsh)。
    • 是人与内核之间的接口。
    • 用户在 Shell 中输入命令,Shell 解析器解析后,调用Linux内核来操作计算机硬件和资源。
image-20250726090558228

shell即是一个程序也是一门程序设计语言:

身份说明
命令行解释器解释用户输入的一条条命令,比如 lscdmkdir 等。
脚本语言像 Python 一样可以写脚本文件,支持变量、函数、if、for、while 等控制结构。

Shell 是用户和 Linux 系统之间的“翻译官”和“控制器”,通过它可以高效、自动化地操作系统和硬件资源。

Shell解析器

Shell解析器就是个程序,读取、解析并执行用户输入的命令行指令

常见的 Shell 解析器有:

Shell 名称路径说明
bash/bin/bash最常见,支持脚本、变量、流程控制等
zsh/bin/zsh比 bash 更强大,支持自动补全、高自定义
sh/bin/sh原始 Shell,兼容性好,功能较基础
fish/usr/bin/fish用户友好,语法简洁,无需 $ 符号等
csh/bin/csh类 C 语法,较老旧,语法不推荐初学者用
tcsh/bin/tcshcsh 的改进版,加入了命令补全等功能
shell
# 看当前登录 Shell 的路径
echo $SHELL         # 读取解析器类型的环境变量

# 输出/bin/bash

Shell脚本编写规范

  • shell脚本就是一个文本文件,一般用.sh作为后缀

  • 首行设置shell解析器类型

    • shell解析器不是好多种嘛,bash,zsh之类的,说明具体用哪种,并给出解析器路径

    • shell
      #!/bin/bash
  • 注释:

    • 单行注释

      shell
      # 我是注释
    • 多行注释

      bash
      :<<!
      我是注释
      我是注释
      !

      image-20250726093524591

多命令处理

在sh脚本中编写多个命令

image-20250726095013639

bash
#! /bin/bash

mkdir -p /root/itheima
echo "hello world" >/root/itheima/one.txt
shell
# 在目录/root下创建itheima目录,并创建一个one.txt的文件,在文件中添加hello world
mkdir -p /root/itheima && touch one.txt && echo "hello world" >>one.txt

多命令连接方式:

  • && :逻辑“与”:

    • 前一条命令返回值为 0(成功)时,才会执行下一条命令。

    • shell
      mkdir -p /root/itheima && echo "目录创建成功"
  • || :逻辑“或”:

    • 前一条命令返回值非 0(失败)时,才会执行下一条命令。

    • shell
      mkdir /root/itheima || echo "目录创建失败"
  • &&||也可以结合起来使用,两者结合,常用于判断执行结果并分别处理。

    • shell
      mkdir -p /root/itheima && (echo "成功") || echo "失败"

变量

变量有3种:

  • 环境变量
  • 自定义变量
  • 特殊变量

环境变量

环境变量是操作系统用来存储配置信息的**“共享变量**”,指定了操作系统的运行环境参数,能够在多个程序之间共享这些配置信息。

环境变量分为两类:

  • 系统环境变量:存储系统范围内的配置信息,供所有用户和多个程序共享。例如,临时文件夹路径、系统目录路径等。

  • 用户级别环境变量:由用户自行定义,只在该用户的Shell会话及其启动的程序中生效,用于配置用户特定的环境,比如用户目录路径、用户自定义的命令路径等。

Shell的配置文件

  • 全局配置文件(系统范围,所有用户生效)
    • /etc/profile
    • /etc/profile.d/*.sh
    • /etc/bashrc
  • 个人配置文件(仅当前用户生效,存放在家目录)
    • /.bash_profile
    • /.bashrc

一般情况下:

  • 不建议直接修改全局配置文件,除非你是系统管理员,需要给所有用户设置统一配置
  • 普通用户或者开发者通常修改自己的个人配置文件,如 ~/.bashrc~/.bash_profile
    • 个人配置文件可以覆盖或补充全局配置,灵活且安全

查看环境变量

查看系统环境变量

shell
env

查看所有变量(系统+自定义+函数)

shell
set

常见环境变量

变量名说明示例值
PATH命令搜索路径,决定Shell找命令的位置/usr/local/bin:/usr/bin:/bin
HOME当前用户的家目录/home/username
USER当前登录用户名username
SHELL当前默认Shell的路径/bin/bash
PWD当前工作目录/home/username/projects
OLDPWD上一个工作目录/home/username
LANG系统语言和区域设置en_US.UTF-8
TERM终端类型,用于终端显示控制xterm-256color
EDITOR默认文本编辑器vimnano
LOGNAME登录名username
MAIL用户邮件存放路径/var/mail/username
PS1Shell 提示符格式[\u@\h \W]\$
UID当前用户ID1000
TMPDIR临时文件目录/tmp
/home/username/.bash_history
shell
# 查看当前系统的编码方式
echo $LANG

环境变量-加载流程原理

先说Shell工作环境,可以俩角度看

  1. Shell工作环境:交互式Shell和非交互式Shell

    • 交互式Shell:就是黑框框里用户输入一个命令,立马出结果就是交互式
    • 非交互式:不需要用户参与,比如执行.sh脚本文件
  2. 登陆Shell环境和非登陆Shell环境

    • 登陆Shell环境:需要用户名和密码登录的shell环境
    • 非登陆Shell环境:
      • 不需要用户名和密码登录的shell环境
      • 执行脚本文件

image-20250525195701129

识别shell环境类型

shell
$0

# 输出-bash代表为登录环境
# 输出bash代表非登录环境

配置系统环境变量

当用户进入Shell环境时,Shell促使话会去加载全局配置文件/etc/profile里面的环境变量,供所有shell程序使用

image-20250726100825383

**举个例子说明咋配置:**在/etc/profile中存储自定义的全局共享环境变量数据

  1. 编辑配置文件,环境变量建议变量名大写
shell
# 定义变量var1="test",并导出为全局变量
export VAR1="test"
  1. reload配置文件
shell
source /etc/profile
  1. 测试配置是否成功
shell
echo $VAR1

小结

image-20250726102023475

自定义变量

自定义变量有三类:

image-20250726102141897

自定义局部变量

局部变量:只能在某个脚本中使用的变量

shell
name="nick"

注意:定义变量时,等号前后不能有空格,因为在bash中,空格是有意义的,塔最基本的分割符,用来分割命令和参数,如果写name = 'nick'的话,bash会把name识别成一个命令,然后=是参数

在shell中,默认所有的变量类型都为字符串

查询变量

$变量${变量}查询

shell
# 写法一
echo "My name is $name"

# 写法二:适合拼接字符串
echo "My name is ${name}"

写法二的查询方式,适合拼接字符串,如下

shell
skill="python"
echo "I'm good at ${skill}Script"

此时不加花括号,bash就会把$skillScript识别为变量,该变量不存在,打印为空

自定义常量(只读变量)

定义后的值不可被更改

使用 readonly命令可以将变量定义为只读变量,只读变量的值不能被改变。

如果尝试改变只读变量,会报错

shell
userID="000345q45q3eesfd"
readonly userID

userID="changed"

# 报错
practice.sh: line 13: userID: readonly variable

删除变量

使用unset命令可以删除变量。

注意:unset不能删除可读变量,会报错

shell
# 删除变量
name="nick"
unset name

# 只读变量不可删除,会报错
userID="000345q45q3eesfd"
readonly userID
unset userID

#报错
practice.sh: line 20: unset: userID: cannot unset: readonly variable

自定义全局变量

得先知道啥是父子shell环境

shell
# 假设现在俩shell脚本,`A.sh`和`B.sh`

# 如果在`A.sh`脚本文件中执行了`B.sh`脚本文件,那么`A.sh`就是父shell环境,`B.sh`就是子shell环境

再来看看啥是全局变量

shell
# 在当前shell环境定义的变量,若用 export 声明为环境变量,

# 它既可以在当前shell中使用,也可以被当前shell启动的子shell继承使用

自定义全局变量语法

shell
export var1 var2

举个例子

A.sh

shell
#!/bin/bash

export var1="hello"
var2="world"

echo "now is A.sh"
echo $var1 $var2

# 调用B.sh
./B.sh

B.sh

shell
#!/bin/bash

echo "var1 is global variable:${var1}" 
echo "var2 is normal variable:${var2}"

执行结果

bash
[u10260225@smart-notebook-7768d67c45-88w4r shellPractice]$ ./A.sh
now is A.sh
hello world
var1 is global variable:hello
var2 is normal variable:

可以看到,在B的打印结果中,只有全局变量var1被打印出来,非全局变量var2的打印结果为空

小结

image-20250726104105242

特殊符号变量

$n

含义

shell
# 用于接收脚本文件执行时传入的参数

# $0,用于获取当前脚本文件名字

# $1~$9,用于获取输入脚本的第一个到第九个参数
	# 获取第10个以上的输入参数:${数字},否则无法获取

执行脚本文件时,传入参数的语法

shell
sh 脚本文件 输入参数1 输入参数2 ...

举个例子:

shell
#!/bin/bash

echo "当前文件名为:$0"
echo "第1个传入参数为:$1"
echo "第2个传入参数为:$2"

输出:

[u10260225@smart-notebook-7768d67c45-88w4r shellPractice]$ ./test.sh 1 2
当前文件名为:./test.sh
第1个传入参数为:1
第2个传入参数为:2

$#

**含义:**获取所有输入参数的个数

举个例子:

shell
#!/bin/bash

echo "一共获取了${#}个参数"

# 输出
[u10260225@smart-notebook-7768d67c45-88w4r shellPractice]$ ./test.sh 1 2
一共获取了2个参数

$*$@

image-20250726105542375

image-20250726110109052

image-20250726110151768

$?

image-20250726110429272

$$`

image-20250726110604400

小结

image-20250726110948403

字符串

Shell里字符串有3种写法:

  • 单引号
    • 使用单引号的字符串会原样输出里面的内容,在其中使用变量是无效的
  • 双引号(推荐)
    • 可以在其中使用变量,eg:var1="i am ${name}"
  • 不加引号
    • 通过空格解析,因此这种方式字符串中间不能用空格
shell
# 使用单引号,变量不生效
name="nick"
echo 'length:${#name}' # 输出:length:${#name}


#使用双引号,变量生效
name="nick"
echo "length:${#name}" #输出:length:4

获取字符串长度

打印字符串长度,使用#

shell
name="nick"
echo "The length of name is ${#name}"

#输出
The length of name is 4

字符串拼接

三种方式:

  1. 无符号拼接
  2. 双引号拼接(推荐)
  3. 混合拼接
shell
var1="hong"
var2="hello world"

# 无符号拼接
var3=${var1}${var2}
echo vars

# 双引号拼接
echo "${var1} ${var2}"

# 混合拼接
var3=${var1}'&'${var2}

字符串截取(提取子字符串)

语法:

shell
${变量名:起始位置:长度}

从 0 开始计数,左闭右开,支持正则

shell
str="hello world"

echo ${str:0:5}   # 输出 hello
echo ${str:6}     # 输出 world(从索引6开始直到末尾)


# 从后往前截取5个字符
echo ${str: -5} 

# 从右侧第5个字符开始,向右侧截取2个字符
echo ${str:0-5:2}

image-20250726161111057

数组

image-20250726161219577

Shell只支持一维数组,不支持多维数组。

从0开始数,数组用空格隔开,不是逗号

定义数组

image-20250726161417450

数组的查询

image-20250726161740172

image-20250726162118733

数组的拼接

image-20250726162314009

数组的删除

image-20250726162605504

shell内置命令

image-20250726163041321

image-20250726163730280

内置命令:read读取控制台输入

image-20250726164235569

示例1:多个变量赋值

image-20250726170408556

image-20250726170442598

示例2:读取一个字符

image-20250726170622100

image-20250726170902162

image-20250726171012681

示例3:限时输入/静默模式

image-20250726172109840

image-20250726172003545

内置命令:exit

image-20250726172502227

image-20250726172549417

image-20250726172639165

示例:shell脚本中使用exit退出

image-20250726172821213

image-20250726172958136

image-20250726173029168

内置命令:declare设置变量

image-20250727101609323

功能一:设置变量属性

image-20250727101851950image-20250727102132555

功能2:实现key-value关联数组变量语法

image-20250727102336950

image-20250727103049250

Shell运算符

算数运算符

image-20250727103801791

expr命令

image-20250727104001032

image-20250727104219183

比较运算符

整数比较

image-20250727140906024

image-20250727141500965

字符串比较

image-20250727141617361

image-20250727141702810

image-20250727142111975

image-20250727142740451

[][[]]的区别

image-20250727142931459

image-20250727143443701

image-20250727143450473

布尔运算符

image-20250727143743542

image-20250727144443561

image-20250727144629232

逻辑运算符

image-20250727144701227

image-20250727144906934

文件测试运算符

image-20250727145513642

image-20250727145618106

image-20250727150455650

image-20250727150536360

image-20250727150418924

image-20250727150743347

shell计算命令

expr

image-20250727150851233

image-20250727150928583

image-20250727151229271

image-20250727151623835

(())命令

image-20250727155841342

image-20250727155906526

image-20250727162028725

let

image-20250727162100702

image-20250727162421027

$[]

image-20250727162754571

image-20250727163002511

流程控制

If else

image-20250803142007259

image-20250803142039319

If条件判断句的退出状态

image-20250803142756832

Released under the MIT License.