神铸利刃·装备养成活动门户

shell编程之shell介绍和变量

shell摘要

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。

Shell 是一种用户与操作系统交互的接口程序,它位于用户与操作系统内核之间,为用户提供了一个交互式的命令行界面或脚本执行环境。用户可以通过 Shell 输入命令,操作系统根据这些命令执行相应的操作。

Shell 是一个命令解释器,它读取用户输入的命令,解析这些命令,并将它们传递给操作系统内核执行。例如,用户输入 ls 命令,Shell 会解析该命令并调用操作系统中的文件列出功能。

Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Shell 脚本(shell script),是一种为 shell 编写的脚本程序,业界所说的 shell 通常都是指 shell 脚本。

shell环境

Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

Linux 的 Shell 种类众多,常见的有:

Bourne Shell(/usr/bin/sh或/bin/sh)

Bourne Again Shell(/bin/bash)

C Shell(/usr/bin/csh)

K Shell(/usr/bin/ksh)

Shell for Root(/sbin/sh)

……

本文关注的是 Bash,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数Linux 系统默认的 Shell。

在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。

#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。

第一个shell脚本

vim hello_world.sh

#!/bin/bash

echo 'hello world'

执行脚本前置操作:需要授予脚本可执行权限,chmod +x hello_world.sh

执行脚本:./hello_world.sh或者bash hello_world.sh

root@master01:~/shell$ ./hello_world.sh

hello world

root@master01:~/shell$ bash hello_world.sh

hello world

步骤详解

shell脚本文件是以.sh结尾,和其它语言的类似,例如Java文件是以.java结尾。python文件是以.py结尾,这个很好理解

shell文件开头必须以#!/bin/bash开头,且不能有其它的内容,这个是强制的,其主要作用是指定脚本默认的命令解释器

脚本内容就是一些shell命令,其实整个shell脚本可以理解成一堆Linux的命令(shell命令)组成的一个合集

脚本执行权限,这里涉及到Linux的一些权限相关的知识,可以参考这篇文章-->《Linux权限之基础权限》

执行脚本有两种方式,一个直接使用./即可,这个有过Linux操作的同学应该都知道,还有另一种就是使用bash或者sh,这里建议使用bash

shell变量类型

shell中变量类型具体可分为字符串类型、整数类型和数组类型

字符串类型

字符串类型使用单引号或者双引号都可,但是其中有点区别,详细内容可看下文-->字符串详解

示例:

name='huangSir'

content="HuangSir Like Linux"

整数类型

整数类型可以直接给值即可。

示例:

num=1

count=99

数组类型

数组类型用于存储多个值,每个值可以通过索引访问,

数组定义方式

# 第一种方式,直接全赋值

arr=("apple" "banana" "cherry")

# 第二种方式,通过索引进行赋值

array_name[0]=value0

array_name[1]=value1

# 第三种方式,通过read命令进行赋值

read -p "xxx" -a array

数组取值方式

#通过索引进行取值

${arr[0]}"

${arr[1]}"

#取出所有元素

${arr[@]}

${arr[*]}

#获取数组的元素个数

${#arr[@]}

${#arr[*]}

shell变量分类

shell中变量分为三类,

普通变量:在脚本中以key=value形式创建的就是普通变量

环境变量:一般是系统创建,例如PATH、PS1、LANG...,变量名是大写

特殊变量:$+特殊符号例如$1、$@,是shell编程的核心

普通变量

在 Shell 编程中,变量是用于存储数据值的名称。有过其它编程语言经验的同学应该很好理解变量的作用,定义变量的语法如下:

key=value

name=zhangsan

变量命名注意事项

变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。

只包含字母、数字和下划线:变量名可以包含字母(大小写敏感)、数字和下划线 _,不能包含其他特殊字符。

不能以数字开头:变量名不能以数字开头,但可以包含数字。

避免使用 Shell 关键字:不要使用Shell的关键字(例如 if、then、else、fi、for、while 等)作为变量名,以免引起混淆。

使用大写字母表示常量:习惯上,常量的变量名通常使用大写字母,例如 PI=3.14。

避免使用特殊符号:尽量避免在变量名中使用特殊符号,因为它们可能与 Shell 的语法产生冲突。

避免使用空格:变量名中不应该包含空格,因为空格通常用于分隔命令和参数。

变量取值

取值方式使用$变量名或者${变量名},两者都是取变量值,区别就是识别变量边界,例如下面的案例

root@master:~/shell$ name=huangSir

root@master:~/shell$ echo $name

huangSir

root@master:~/shell$ echo ${name}

huangSir

root@master:~/shell$ echo $namedevops

root@master:~/shell$ echo ${name}devops

huangSirdevops

其中可以发现echo $namedevops并没有输出任何内容,但是echo ${name}devops输出了预期的字符串,这个就是它俩的区别

只读变量

只读变量的就是定义之后不允许修改,当你尝试修改时,解释器会进行提示,使用关键字readonly进行定义

root@master:~/shell$ name=huangSir

root@master:~/shell$ readonly name

root@master:~/shell$ name=tom

-bash: name: readonly variable

上面这个案例就是当我们定义name值为huangSir后,我们使用readonly设置name为只读,然后我们尝试修改name字段,然后解释器提示name: readonly variable

环境变量

环境变量又叫做全局变量,环境变量是一处定义,整个系统都可以使用,大部分环境变量都哦是系统定义好的,我们一般就是进行修改使用

查看环境变量

我们可以使用env命令来查看当前系统所有的环境变量

root@master:~/shell$ env

SHELL=/bin/bash

LIBGL_ALWAYS_INDIRECT=1

WSL2_GUI_APPS_ENABLED=1

WSL_DISTRO_NAME=Ubuntu

NAME=5CG422112V-QCA

# 省略万字内容

...

SSH_TTY=/dev/pts/2

HOSTTYPE=x86_64

PULSE_SERVER=unix:/mnt/wslg/PulseServer

_=/usr/bin/env

查看指定的环境变量可以配合grep命令或者使用`echo $变量名

root@master:~/shell$ env | grep LANG

LANG=C.UTF-8

root@master:~/shell$ echo $LANG

C.UTF-8

常用的环境变量

PATH:记录命令位置的环境变量,运行命令的时候bash会在PATH的路径中去找

LANG:系统语言字符集,设置中文为LANG=zh_CN.UTF8

PS1:命令行格式

UID或者EUID:用户的uid,用于判断当前用户是否为root,root用户的uid为0,我们可以在脚本中进行判断用户是否为root

设置环境变量

使用export可以添加、修改当前系统的环境变量,例如我们要添加一个APP=Linux的环境变量

root@master:~/shell$ export APP=Linux

root@master:~/shell$ echo $APP

Linux

root@master:~/shell$ env | grep APP

APP=Linux

我们将APP的值修改为Windows

root@master:~/shell$ export APP=Windows

root@master:~/shell$ echo $APP

Windows

删除环境变量

使用unset 变量名可以删除环境变量,当然unset不仅仅可以删除环境变量,普通变量也可以删除

我们将上面设置的APP变量进行一个删除

root@master:~/shell$ unset APP

root@master:~/shell$ echo $APP

root@master:~/shell$

环境变量与相关文件及目录

环境变量与操作系统的文件和目录密切相关,它们在系统启动、用户登录、程序运行等过程中被设置和使用。

以下是一些与环境变量相关的重要文件和目录

/etc/profile

作用:

是一个系统级的 Shell 脚本,用于设置全局的 Shell 环境变量和初始化脚本。

在用户登录时被加载。

/etc/bashrc

作用:

主要用于存放Linux系统别名

~/.bashrc

作用:

是用户主目录下的 Shell 配置文件,用于设置用户级的环境变量和 Shell 配置。

在每次打开新的 Shell 时被加载(适用于交互式 Shell)。

~/.bash_profile

作用:

是用户主目录下的 Shell 配置文件,用于设置用户级的环境变量和初始化脚本。

在用户登录时被加载(适用于登录 Shell)。

/etc/profile.d/

作用:

这是个目录,每个用户登录的时候(远程连接与su切换),加载目录下面的.sh文件

如果修改了上面的文件之后,想让其生效,需要使用source 配置文件让其加载生效

上述配置文件加载顺序

首先加载/etc/profile

然后按照顺序依次加载~/.bash_profile,~/.bashrc,/etc/bashrc

最后加载/etc/profile.d/目录下的内容

特殊变量

在 Shell 脚本中,特殊变量是预定义的变量,用于存储特定的信息,由$+特殊符号组成,例如$1、$@,是shell编程的核心。这些信息通常与 Shell 的运行状态或脚本的执行有关。

为了学习,这里定义特殊变量又分为两类,一类是位置变量,另一类是状态变量

特殊变量之位置变量

$N:执行脚本传入的第N个参数,N代表一个数字,例如$1、$2等等

$0:表示脚本的文件名

$#:表示脚本参数的个数

$@:取出脚本中所有的参数放入到一个数组中

$*:取出脚本中所有的参数放入到一个字符串中

示例:

root@master:~$ cat specual_var.sh

#!/bin/bash

echo '脚本名称:'$0

echo '脚本第一个参数:'$1

echo '脚本一共有几个参数:'$#

echo '脚本所有的参数:'$@

echo '脚本所有的参数(字符串):'$*

#执行之后的结果

root@master:~$ ./specual_var.sh 1 2 3 4

脚本名称:./specual_var.sh

脚本第一个参数:1

脚本一共有几个参数:4

脚本所有的参数:1 2 3 4

脚本所有的参数(字符串):1 2 3 4

特殊变量之状态变量

$?:判断上一条命令是否执行成功,一般与if判断联合起来使用

$$:当前脚本/命令的pid

$!:上一个脚本/命令的pid

$_:上一个命令的最后一个参数

示例:

root@master:~$ echo 'huangSir'

huangSir

#上一条命令成功为0,不为0代表失败

root@master:~$ echo $?

0

#当前命令的pid,也代表当前bash命令的pid

root@master:~$ echo $$

341

shell中变量赋值方式

变量赋值就是向变量中写入内容,变量赋值方式在shell中一般有以下几种方式

直接赋值

root@master:~$ name=huangSir

root@master:~$ echo $name

huangSir

命令结果赋值

使用反引号(注意,不是单引号)可以获取到命令的值

root@master:~$ hostname=`hostname`

root@master:~$ echo $hostname

master

脚本传参的方式

#!/bin/bash

name=$1

age=$2

read交互式赋值

通过read命令实现

示例一:指定提示符 -p选项,-p选项可以指定一个提示符,提示用户输入内容

#常用

root@master:~$ read -p "请输入密码:" passwd

请输入密码:123

root@master:~$ echo $passwd

123

示例二:静默模式,通过-s选项实现,-s选项用于静默模式,即隐藏用户输入的内容,这在输入密码等敏感信息非常有用

root@master:~$ read -s -p "请输入密码:" passwd

请输入密码:

root@master:~$ echo $passwd

123456

示例三:数组模式,一次输入多个变量,通过-a选项,将多个变量存入到数组中

root@master:~$ read -a arr -p "请输入多个域名,用空格分开"

请输入多个域名,用空格分开www.baidu.com www.jd.com www.taibao.com

#${arr[@]}打印数组中所有的元素

root@master:~$ echo ${arr[@]}

www.baidu.com www.jd.com www.taibao.com

root@master:~$ echo ${arr[*]}

www.baidu.com www.jd.com www.taibao.com

给变量设置默认值

有几种方式,分别如下:

${param:=value}

常用的只有这么一个

变量param没定义时,创建param变量并设置默认值为value,如果已定义变量,但是值为空时,会将value赋值

示例:

#未定义变量,前面有一个冒号

root@master:~$ : ${name:='huangSir'}

root@master:~$ echo $name

huangSir

#定义变量为空

huangxin@5CG422112V-QCA:~$ age=

huangxin@5CG422112V-QCA:~$ : ${age:=26}

huangxin@5CG422112V-QCA:~$ echo $age

26

其它方式,自行测试

#变量param没定义时,创建param变量并设置默认值为value,如果已定义变量,但是值为空时,会将value赋值,但是不会修改的变量的值

${param:-value}

#变量未定义或者为空时,啥也不做,否则会修改变量值为value

${param:+value}

#变量未定义或者为空时,显示value,是错误输出

${param:?value}