3.Shell 变量基础知识

作者@小郭

3. Shell 变量基础知识

3.1 什么是 Shell 变量

3.1.1 什么是变量

简单地说,变量名是用一个固定的字符串(字符、数字和下划线的组合,不能以数字开头)代替更多、更复杂的内容,该内容里可能还会包含变量、路径、字符串等其他的内容。

变量 是暂时存储数据的地方及数据标记,所存储的数据存在于内存空间中,通过正确地调用内存空间中变量的名字就可以取出与变量对应的数据。使用变量的最大好处就是使程序开发更为方便,当然,在编程中使用变量也是必须的,否则就很难完成相关的程序开发工作。

下面是定义变量和打印变量的示例:

bash 复制代码
# 定义变量,名字为username,对应的内容gcf
[root@server ~ 09:39:04]# username= "gcf"


# 打印变量的值
[root@server ~ 09:39:14]# echo $username 
gcf

变量的赋值方式为:先写变量名称,紧接着是``字符,最后是值,中间无任何空格。

通过 echo 命令加上 $username 即可输出 username 变量的值。变量的内容一般要加双引号,以防止出错,特别是当值里的内容之间有空格时。

3.1.2 Shell 变量的特性

默认情况下,在bash Shell 中是不会区分变量类型的 。例如:常见的变量类型为整数、字符串、小数等都当做字符串变量。这和其他强类型语言(例如:Java/C语言)是有区别的,当然,如果需要指定 Shell 变量的类型,也可以使用 declare 命令定义变量的类型,但在一般情况下没有这个需求。

3.1.3 变量类型

变量根据范围可分为两类:

  • 全局变量 ,在创建它们的 Shell 及其派生出来的任意子进程 Shell 中使用

  • 局部变量,只能在创建它们的 Shell 函数或 Shell 脚本中使用。

变量根据是否是用户自定义也可分为两类:

  • 普通变量:也称为常规变量,由开发者在开发脚本程序时创建。
  • 环境变量:定义shell 执行环境。环境变量又可分为自定义环境变量和bash内置的环境变量。

3.2 环境变量

环境变量一般是指用export内置命令导出的变量,用于定义 Shell 的运行环境,保证 Shell 命令的正确执行。 Shell 通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等,所有的环境变量都是系统全局变量,可用于所有子进程中,这包括编辑器、 Shell 脚本和各类应用。

环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,因此,如果希望永久保存环境变量,可在用户家目录下的 .bash_profile.bashrc(非用户登录模式特有,例如远程SSH)文件中,或者全局配置 /etc/bashrc (非用户登录模式特有,例如远程SSH)或 /etc/profile 文件中定义。在将环境变量放入上述的文件中后,每次用户登录时这些变量都将被初始化。

按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用 export 命令导出定义。有一些环境变量,比如HOMEPATHUSER等,在用户登录之前就已经被/bin/login程序设置好了。通常环境变量被定义并保存在用户家目录下的 .bash_profile 文件或全局的配置文件 /etc/profile 中。

部分bash环境变量展示:

  • EDITOR,默认编辑器。
  • HISTFILE,历史文件位置。
  • HISTSIZE,历史命令个数。
  • PS1,命令行提示符。
  • LANG,Shell 环境语言。
  • PATH,命令搜素路径。
  • HOME,当前用户家目录。
  • USER,当前用户。
  • PWD,当前 Shell 路径。
  • IFS,字符串分隔符。

在查看设置的变量时,有3个命令可以显示变量的值:

  • set 命令 ,输出所有的变量,包括全局变量和局部变量。
  • env 命令 ,只显示全局变量,包括shell的环境。
  • declare 命令输出所有的变量、函数、整数和已经导出的变量set -o 命令显示bash Shell 的所有参数配置信息。

3.2.1 设置环境变量

1. 设置环境变量

如果想要设置环境变量,就要在给变量赋值之后或在设置变量时使用export命令,具体设置见下文的示例。其实,除了 export 命令,带-x选项的declare内置命令也可以完成同样的功能(注意:此处不要在变量名前面加$)。

export 命令和 declare 命令的格式如下:

  • export 变量名=value
  • 变量名=value ; export 变量名
  • declare -x 变量名=value

示例:

bash 复制代码
export NAME=gcf
declare -x NAME=gcf
NAME=gcf; export NAME

下面来看看让环境变量永久生效的常用设置文件。

  • 用户的环境变量配置文件~/.bash_profile~/.bashrc推荐在(~/.bashrc)文件中设置。

  • 全局环境变量的配置文件/etc/profile/etc/bashrc/etc/profile.d/。**推荐在 /etc/bashrc 文件中设置。**若要在登录后初始化或显示加载内容,则把脚本文件放在/etc/profile.d/下即可(无须加执行权限)。

2. 设置登录后提示信息
  1. 第一种是在 /etc/motd 里增加提示的字符串,如下:

    bash 复制代码
    [root@server ~ 09:41:18]# vim  /etc/motd
     hello gcf
    
    #登录后效果
    WARNING! The remote SSH server rejected X11 forwarding request.
    Last login: Thu Dec  4 09:38:21 2025 from 10.1.8.1
    #多了这一行
    hello gcf
  2. 第二种是在 /etc/profile.d/ 下面增加如下脚本。

    bash 复制代码
    [root@server ~ 09:44:45]# vim /etc/profile.d/gcf.sh
    hello  gcf

补充

  • 登录前提示符由文件 /etc/issue 提供。
bash 复制代码
[root@server ~ 09:45:22]# vim /etc/issue
#添加一行helloworld
[root@server ~ 09:48:28]# cat /etc/issue
\S
Kernel \r on an \m
hello world

重新登录就会显示出来,如图所示:

  • 登录后时间提示符由ssh服务提供:在 /etc/ssh/sshd_config 文件中配置PrintLastLog yes,默认启用。
bash 复制代码
[root@server ~ 09:50:55]# echo PrintLastLog no >>  /etc/ssh/sshd_config

#必须重启服务,不然不生效。
[root@server ~ 09:53:13]# systemctl restart sshd

#观察下图两者对比,使用no 就不会显示上一次登录时间的提示信息

3.2.2 显示与取消环境变量

  1. 通过echoprintf命令打印环境变量。
  2. envset显示默认的环境变量。
  3. unset消除本地变量和环境变量。

3.2.3 环境变量初始化与对应文件的生效顺序

在登录 Linux 系统并启动一个bash shell 时,默认情况下 bash 会在若干个文件中查找环境变量的设置。这些文件可统称为系统环境文件。bash 检查的环境变量文件的情况取决于系统运行 Shell 的方式。

系统运行 Shell 的方式一般有3种:

  1. 通过系统用户登录后默认运行的 Shell 。
  2. 非登录交互式运行 Shell 。
  3. 执行脚本运行非交互式 Shell 。

当用户登录 Linux 系统时, Shell 会作为登录 Shell 启动。此时的登录 Shell 加载环境变量的顺序如下图所示。

  1. 用户登录系统后首先会加载 /etc/profile 全局环境变量文件,这是Linux系统上默认的 Shell 主环境变量文件。系统上每个用户登录都会加载这个文件。

  2. 当加载完/etc/profile文件后,才会执行/etc/profile.d目录下的脚本文件,这个目录下的脚本文件有很多,例如:系统的字符集设置等。

  3. 之后开始运行 $HOME/.bash_profile。在这个文件中,又会去找$HOME/.bashrc:如果有,则执行;如果没有,则不执行。在HOME/.bashrc文件中又会去找/etc/bashrc(全局环境变量文件),如果有,则执行,如果没有,则不执行。

  4. 如果用户的 Shell 不是登录时启动的,比如手动敲下bash时启动,那么这种非登录 Shell 只会加载$HOME/.bashrc(用户环境变量文件),并会去找/etc/bashrc(全局环境变量文件)。

    因此如果希望在非登录 Shell 下也可读到设置的环境变量等内容,就需要将变量设定等写入$HOME/.bashrc或者/etc/bashrc,而不是$HOME/.bash_profile/etc/profile

3.2.4 环境变量的知识小结

  1. 变量名通常要大写。
  2. 变量可以在自身的 Shell 及子 Shell 中使用。
  3. 常用 export 来定义环境变量。
  4. 执行 env 默认可以显示所有的环境变量名称及对应的值。
  5. 输出时用 $变量名,取消时用 unset变量名
  6. 书写 crond 定时任务时要注意,脚本要用到的环境变量最好先在所执行的 Shell 脚本中重新定义。
  7. 如果希望环境变量永久生效,则可以将其放在用户环境变量文件或全局环境变量文件里。

3.3 普通变量

本地变量在用户当前 Shell 生存期的脚本中使用。例如,本地变量gcf的定义为bingbing, 这个值只在用户当前 Shell 生存期中有意义。如果在 Shell 中启动另一个进程或退出,那么变量gcf的值将会无效。

3.3.1 普通变量定义

为普通变量的定义赋值,一般有以下3 种写法:

  • 变量名=value,赋值时不加引号。
  • 变量名='value',赋值时加单引号。
  • 变量名="value",赋值时加双引号。

3.3.2 变量名及变量值要求

  • 变量名 :一般是由字母、 数字 、下划线 组成的,只可以以字母或下划线开头 ,例如:gcfgcf_123gcf_training
  • 变量值:可以用单引号或双引号引起来,也可不加引号,但是这三者的含义是不同的。

3.3.3 普通变量的定义及输出示例

采用不同的方式对普通变量进行定义,并打印输出。

示例1:

bash 复制代码
[root@server ~ 18:33:31]#  a=192.168.1.2
[root@server ~ 18:33:31]# b='192.168.1.2'
[root@server ~ 18:33:31]# c="192.168.1.2"
[root@server ~ 18:33:31]# echo "a=$a"
a=192.168.1.2
[root@server ~ 18:33:31]# echo "b=$b"
b=192.168.1.2
[root@server ~ 18:33:31]# echo "c=${c}"
c=192.168.1.2

可见, 将连续的普通字符串的内容赋值给变量,不管用不用引号,或者不管用什么引号,它的内容是什么,打印变量时就会输出什么。

示例2:

bash 复制代码
[root@server ~ 18:33:31]# a=192.168.1.2-$a
[root@server ~ 18:33:31]# echo "a=$a"
a=192.168.1.2-192.168.1.2

[root@server ~ 18:33:31]# b='192.168.1.2-$a'
[root@server ~ 18:33:31]#echo "b=$b"
b=192.168.1.2-$a

[root@server ~ 18:33:31]# c="192.168.1.2-$a"
[root@server ~ 18:33:31]# echo "c=${c}"
c=192.168.1.2-192.168.1.2-192.168.1.2 
  1. 变量定义的基本技巧总结

    • a=192.168.1.2-$a, 定义a变量的方式是不加任何引号直接定义变量的内容, 当内容为简单连续的数字、字符串、路径名时,可以这样用,例如: a=1,b=gcf等。不加引号时,值里有变量的会被解析后再输出,上述变量定义中因为$a的值被解析为192.168.1.2 ,因此新的a值就是192.168.1.2-192.168.1.2。

    • b='192.168.1.2-$a',定义b 变量的方式是通过单引号定义。

      这种定义方式的特点是:输出变量内容时单引号里是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。 这种方式比较适合于定义显示纯字符串的情况,即不希望解析变量 、命令等的场景,因此, 对于这里的b 的值,定义时看到的是什么就输出什么,即192.168.1.2-$a。

    • c="192.168.1.2-$a",定义c变量的方式是通过双引号定义变量。

      这种定义方式的特点是:输出变量内容时引号里的变量及命令会经过解析后再输出内容,而不是把双引号中的变量名及命令 (命令需要反引起来)原样输出。 这种方式比较适合于字符串中附带有变量及命令且想将其解析后再输出的变量定义。

3.3.4 把命令的结果作为变量的内容赋值

常见方法有两种,以ls命令为例:

  • 变量名=`command` ,把命令用反引号引起来,不推荐使用这种方法,因为容易和单引号混淆。
  • **变量名=(command)∗∗,把命令用∗∗(command)** ,把命令用**(command)∗∗,把命令用∗∗()**括起来 ,推荐使用这种方法。
bash 复制代码
[root@server ~ 18:33:31]# ls
script.sh
[root@server ~ 18:33:31]# CMD1=`ls`
[root@server ~ 18:33:31]# echo $CMD1
script.sh

[root@server ~ 18:33:31]# CMD2=$(pwd)
[root@server ~ 18:33:31]# echo $CMD2
/home/gcf

[root@server ~ 18:33:31]# date +%A
Friday
[root@server ~ 18:33:31]# echo Today is $(date +%A).
Today is Friday.

生产场景中把命令的结果作为变量的内容进行赋值的方法在脚本开发时很常见。

3.4 变量定义技巧总结

可以多学习和模仿操作系统自带的 /etc/init.d/functions 函数库脚本的定义思路,多学习Linux系统脚本中的定义,有经验的读者最终应形成一套适合自己的规范和习惯。

  1. 变量名及变量内容定义小结。

    • 变量名只能包含字母、数字或下划线,只能以字母或下划线开头。

    • 变量名的定义要有一定的规范,并且要见名知意。

      示例:

      bash 复制代码
      # 每个单词的首字母大写的写法
      gcfAge=l
      
      # 单词之间用_
      gcf_age=l
      
      # 驼峰语法:首个单词的首字母小写,其余单词首字母大写
      gcfAge=l8
      gcfSex=man
      
      # 单词全大写
      gcfAGE=1
    • 一般的变量定义、赋值常用双引号;简单连续的字符串可以不加引号;希望原样输出时使用单引号。

    • 希望变量的内容是命令的解析结果时,要用反引号'`',或者用$()把命令括起来再赋值。

  2. Shell 定义变量

    a=1 里等号是赋值的意思;比较变量是否相等时也可以用===

  3. 打印输出及使用变量

    • 打印输出或使用变量时,变量名前要接 $ 符号;变量名后面紧接其他字符的时候,要用大括号将变量部分单独括起来;在unset、export、(())等场景中使用但不打印变量时不加$,这个有些例外。

    • 打印输出或使用变量时,一般加双引号或不加引号;如果是字符串变量,最好加双引号;希望原样输出时使用单引号。

    • 一般的变量定义、赋值常用双引号;简单连续的字符串可以不加引号;希望原样输出时使用单引号。

    • 希望变量的内容是命令的解析结果时,要用反引号'`',或者用$()把命令括起来再赋值。

  4. Shell 定义变量

    a=1 里等号是赋值的意思;比较变量是否相等时也可以用===

  5. 打印输出及使用变量

    • 打印输出或使用变量时,变量名前要接 $ 符号;变量名后面紧接其他字符的时候,要用大括号将变量部分单独括起来;在unset、export、(())等场景中使用但不打印变量时不加$,这个有些例外。
    • 打印输出或使用变量时,一般加双引号或不加引号;如果是字符串变量,最好加双引号;希望原样输出时使用单引号。
相关推荐
Sheep Shaun4 小时前
如何让一个进程诞生、工作、终止并等待回收?——探索Linux进程控制与Shell的诞生
linux·服务器·数据结构·c++·算法·shell·进程控制
dingdingfish1 天前
Bash 学习 - 第1章:Introduction
bash·shell·programming·introduction
pr_note3 天前
legality检查
shell·tcl
啥都不懂的小小白4 天前
Shell脚本编程入门:从零基础到实战掌握
前端·shell
dingdingfish8 天前
GNU Parallel 学习 - 第1章:How to read this book
bash·shell·gnu·parallel
似霰11 天前
Linux Shell 脚本编程——核心基础语法
linux·shell
似霰11 天前
Linux Shell 脚本编程——脚本自动化基础
linux·自动化·shell
偷学技术的梁胖胖yo12 天前
Shell脚本中连接数据库查询数据报错 “No such file or directory“以及函数传参数组
linux·mysql·shell
纵有疾風起21 天前
【Linux 系统开发】基础开发工具详解:软件包管理器、编辑器。编译器开发实战
linux·服务器·开发语言·经验分享·bash·shell
gis分享者23 天前
Shell 脚本中如何使用 here document 实现多行文本输入? (中等)
shell·脚本·document·多行·文本输入·here