Linux - Shell 变量

原创
2018/10/03 16:04
阅读数 111

        变量是暂时存储数据的地方及数据标记,所存储的数据存在于内存空间中,通过正确地调用内存空间中变量的名字就可以取出与变量对应的数据。使用变量最大的好处就是使程序开发更为方便,同时,在编程中如不使用变量也很难完成相关程序开发工作。简单地说,变量就是用一个固定的字符串(字符、数字等组合)代替更多、更复杂的内容,该内容里可能还包含变量、路径、字符串等其他的内容。

        默认情况下,在 bash Shell 中是不会区分变量类型;这和其他强类型语言(例如:Java/C 语言)是有区别的。当然也可以使用 declare 显示定义变量的类型,来指定 Shell 变量类型,但一般情况下没有这个需求。Shell 变量可分为两类:环境变量(全局变量)和普通变量(局部变量)。

一、环境变量

        环境变量也可称为全局变量,可以在创建它们的 Shell 及其派生出来的任意子进程 Shell 中使用,环境变量又可分为自定义环境变量和bash 内置的环境变量。

        环境变量一般是指用 export 内置命令导出的变量,用于定义 Shell 的运行环境,保证 Shell 命令的正确执行。Shell 通过环境变量来确定登陆用户名、命令路径、终端类型、登陆目录等,所有的环境变量都是系统全局变量,可用于所有子进程中,这包括编辑器、Shell 脚本和各类应用。环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,所以在用户家目录下的 .bash_profile 或 bashrc (非用户登录模式特有,例如远程SSH) 文件中,或者,在全局配置 /etc/profile 文件中定义或 /etc/bashrc (非用户登录模式特有,例如远程SSH) 。在将环境变量放入上述的文件中后,每次用户登录时这些变量都将被初始化,也就是可以永久保存环境变量不会随着用户退出命令行这些变量值就会丢失。

        按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用 export 命令导出定义,例如:

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH
JAVA_HOME=/home/redhat/jdk/jdk1.8.0_121
CLASSPATH=$JAVA_HOME/lib/
PATH=$JAVA_HOME/bin:$PATH
export PATH JAVA_HOME CLASSPATH

#zookeeper env
export ZOOKEEPER_HOME=/home/redhat/zookeeper
export PATH=$ZOOKEEPER_HOME/bin:$PATH

        在查看设置的变量时,有3个命令可以显示变量的值:set、env 和 declare( 代替早期的 typeset )。set 命令输出所有的变量,包括全局变量和局部变量;env 命令只显示全局变量;declare 命令输出所有的变量、函数、整数和已导出的变量。set -o 命令显示 bash Shell 的所有参数配置信息。


[redhat@BING ~]$ env|tail
HOME=/home/redhat
LOGNAME=redhat
QTLIB=/usr/lib64/qt-3.3/lib
CLASSPATH=/home/redhat/jdk/jdk1.8.0_121/lib/
SSH_CONNECTION=10.11.63.25 52141 10.100.12.81 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/1000
DISPLAY=localhost:12.0
QT_PLUGIN_PATH=/usr/lib64/kde4/plugins:/usr/lib/kde4/plugins
_=/usr/bin/env
[redhat@BING ~]$ declare|tail
{
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}
quote_readline ()
{
    local quoted;
    _quote_readline_by_ref "$1" ret;
    printf %s "$ret"
}
[redhat@BING ~]$ set -o|head
allexport       off
braceexpand     on
emacs           on
errexit         off
errtrace        off
functrace       off
hashall         on
histexpand      on
history         on
ignoreeof       off

1.1 自定义环境变量

1.1.1 设置环境变量

         设置环境变量的三种方法:

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

# 1、在设置变量时使用 export 命令
export 变量名=value
# 2、再给变量赋值之后,再使用 export 命令
变量名=value; 
export 变量名
# 3、带 -x 选项的 declare 内置命令也可 (此处不要在变量名前面加$)
declare -x 变量名=value

        全局环境变量的配置:

# 常见的全局配置变量的配置文件
/etc/profile

/etc/bashrc         # 推荐在此文件中优先设置

# 若要在登录后初始化或显示加载内容,则把脚本文件放在 /etc/profile.d 下即可(无须加执行权限)
/etc/profile.d

        若要在登录后初始化或显示加载内容,则把脚本文件放在 /etc/profile.d 下即可(无须加执行权限),例如,设置登录提示:

        1)第一种是在 /etc/motd 里增加提示字符串

[redhat@BING ~]$ cat /etc/motd
[redhat@BING ~]$ vim /etc/motd
[redhat@BING ~]$ sudo vim /etc/motd
[redhat@BING ~]$ cat /etc/motd
Welcome to BING Linux.
[redhat@BING ~]$

        2) 第二种是在 /etc/profile.d/ 下面增加如下脚本


[redhat@SHOUFUAP ~]$ cat /etc/profile.d/welcome.sh  # 展示welcome.sh脚本内容
Welcome to BING Linux.

1.1.2 显示或取消环境变量

        1)通过 echo 或 printf 命令打印环境变量


[redhat@BING ~]$ echo $HOME
/home/redhat
[redhat@BING ~]$ echo $UID
1000
[redhat@BING ~]$ echo $PWD
/home/redhat
[redhat@BING ~]$ echo $SHELL
/bin/bash
[redhat@BING ~]$ echo $USER
redhat
[redhat@BING ~]$ printf "$HOME\n"
/home/redhat
[redhat@BING ~]$

# printf 是一个更复杂的格式化打印内容工具
# $HOME: 用户登录时进入的目录
# $UID: 当前用户的 UID (用户标识),相当于 id-u
# $PWD: 当前工作目录的绝对路径名
# $SHELL: 当前 SHELL
# $USER: 当前用户

        在写 Shell 脚本时可以直接使用系统默认的环境变量,一般情况下时是不需要重新定义的,在使用定时任务等执行 Shell 脚本时建议在脚本中重新定义。

        可以用 env 或 set 显示默认的环境变量;也可以用 unset 消除本地变量和环境变量。

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

    在登录Linux系统并启动一个bash shell时,默认情况下bash会在若干个文件中查找环境变量的设置。这些文件可统称为系统环境变量。bash检查的环境变量文件的情况取决于系统运行shell的方式。
系统运行shell的方式一般有三种:
    1) 通过系统用户登录后默认运行的shell
    2) 非登录交互式运行shell
    3) 执行脚本运行非交互式shell
    当用户登录Linux系统时,shell会作为登录shell启动。登录 Shell 读取环境变量文件的流程如下:

 

 

 

 

 

 

 

 

 

 

         用户登录系统后首先会加载/etc/profile全局变量文件,这是Linux系统上默认的shell主环境变量文件。系统上每个用户登录都会加载这个文件。当加载完/etc/profile文件后,才会执行/etc/profile.d目录下的脚本文件。之后开始运行$HOME/.bash_profile(用户环境变量文件),在这个文件中,又会去找$HOME/.bashrc(用户环境变量文件),如果有则执行,如果没有则不执行。在$HOME/.bashrc文件中又会去找/etc/bashrc(全局环境变量文件),如果有则执行,如果没有则不执行。
    如果用户的shell不是登录时启动的,非登录shell只会加载$HOME/.bashrc(用户环境变量文件),并会去找/etc/bashrc(全局环境变量文件)。如果希望在登录shell下也可以读到设置的环境变量等内容,就需要将变量设定等写入$HOME/.bashrc或者/etc/bashrc,而不是$HOME/.bash_profile或/etc/profile。
 

1.2 普通变量

1.2.1 定义本地变量

        本地变量(局部变量) 在用户当前 Shell 生存期的脚本中使用。变量名一般是由字母、数字、下划线组成的,可以以字母或下划线开头;变量的内容可以用单引号或双引号引起来,也可不加引号,但三者含义是不同的。为普通变量的定义赋值,一般有以下三种写法:   

# 赋值时不加引号
变量名=value

# 赋值时加单引号
变量名='value'

# 赋值时加双引号
变量名="value"

        采用不同的方式对普通变量进行定义的差异如下( $变量名表示输出变量,可以用 $变量名 和 ${变量名} ):

        1) 定义 x 变量的方式是不加任何引号直接定义变量的内容,当内容为简单连续的数字、字符串、路径名时,可以这样用;其特点:不加引号时,值里有变量的会被解析后输出

# 定义变量
x=192.168.1.1-$x

# 输出结果($x的值被解析)
x=192.168.1.1-192.168.1.1

        2) 定义 y 变量的方式是通过的的单引号定义,其特点:输出变量内容时单引号里是什么就输出什么,即使内容中有变量和命令(命令需要反引号`` 引起来)也会原样输出

# 定义变量
y='192.168.1.1-$x'

# 输出结果($x的值不会被解析)
y=192.168.1.1-$x

        3) 定义 z 变量的方式是通过双引号定义变量,其特点:输出变量内容时引号里的变量及命令会经过解析后在输出内容,而不是把双引号中的变量名及命令(命令需要反引号`` 引起来)

# 定义变量
z=192.168.1.1-$x

# 输出结果($x的值被解析)
z=192.168.1.1-192.168.1.1-192.168.1.1

        所以数字内容的变量定义可以不加引号,其他没有特别要求的字符串等定义最好都加上双引号,如果真的的需要原样输出就加单引号。同时,把一个命令的结果作为变量的内容赋值的方法在脚本开发中也是很常用的。

        对需要获取命令结果的变量内容赋值的常见方法有两种:


# 把命令用反引号引起来(容易和单引号混淆)
变量名=`ls`

# 把命令用 $() 括起来
变量名=$(ls)


[redhat@BING jdk]$ ls
jdk1.8.0_121  jdk-8u121-linux-x64.tar.gz
[redhat@BING jdk]$ CMD=`ls`
[redhat@BING jdk]$ echo $CMD
jdk1.8.0_121 jdk-8u121-linux-x64.tar.gz
[redhat@BING jdk]$ echo ${CMD}
jdk1.8.0_121 jdk-8u121-linux-x64.tar.gz
[redhat@BING jdk]$ CMD_PWD=$(pwd)
[redhat@BING jdk]$ echo $CMD_PWD
/home/redhat/jdk
[redhat@BING jdk]$ echo ${CMD_PWD}
/home/redhat/jdk
[redhat@BING ~]$ echo H=$(date)
H=Thu Oct 4 13:22:58 CST 2018
[redhat@BING ~]$ echo zcf etc_$(date +%F).tar.gz /etc           # tar: 从成员名中删除开头的“/” ; tar: 从硬连接目标中删除开头的“/”
zcf etc_2018-10-04.tar.gz /etc
[redhat@BING ~]$ H=$(uname -n)
[redhat@BING ~]$ echo ${H}
BING
[redhat@BING ~]$ echo zcf $H.tar.gz /etc/services               # tar: 从成员名中删除开头的“/”
zcf BING.tar.gz /etc/services
[redhat@BING ~]$

        echo 、sed 、grep 调用是符合上述结论的,但是当使用 awk 调用 Shell 中的变量时,会有一些特殊用法。就是不管变量如何定义、赋值,除了加单引号以外,利用 awk 直接获取变量的输出,结果都一样,因此,在 awk 取用 Shell 变量时,最好是先用 echo 加符号输出变量,然后通过管道给 awk ,进而控制变量的输出结果。

 

展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部