shell-的变量

本文详细介绍了Shell中的全局变量、局部变量和特殊变量,包括环境变量的设置与导出、局部变量的定义、位置变量、进程状态变量的用法,以及变量的字符串操作技巧,是理解Shell脚本编程的重要参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、shell全局变量

提示:

1.在变量名前加 $,可以取得此变量的值,使用echo命令可以显示变量值,
$A${A} 的写法不同,但是功能是一样的。推荐使用后者的语法或
 "${A}" 的用法。
2.${WEEk}day 若变量和其他字符组成新的变量就必须给变量加大括号{}。
这样才能区分哪个是变量,那个是字符。

1. 变量类型
  变量可分为两类:环境变量(全局变量)和局部变量。
  环境变量也可称为全局变量,可以在创建他们的shell及其派生出来的任意子进程shell中使用。局部变量只能在创建他们的shell函数或脚本中使用。还有一些变量是用户创建的其它的则是专用shell变量。
2. 环境变量
  环境变量用于定义shell的运行环境,保证shell命令的正确执行,shell通过环境变量来确定登陆用户名、命令路径、终端类型、登陆目录等,所有的环境变量都是系统全局变量,可用于所有子进程中,这包括编辑器、shell脚本和各类应用。
  环境变量可以在命令行中设置,但用户退出时这些变量值也会丢失,因此最好在用户家目录下的.bash_profile文件中或全局配置/etc/profile文件或者/etc/profile.d/中定义。将环境变量放入profile文件中,每次用户登录时这些变量值都将被初始化。
  传统上,所有环境变量均为大写。环境变量应用于用户进程前,必须用export命令导出
  环境变量可用在创建他们的shell和从该shell派生的任意子shell或进程中。他们通常被称为全局变量以区别局部变量。通常,环境变量应该大写。环境变量是已经用export内置命令导出的变量。
  有一些环境变量,比如HOME、PATH、SHELL、UID、USER等,在用户登录之前就已经被/bin/login程序设置好了,通常环境变量定义并保存在用户家目录下.bash_profile文件中。具体的环境变量说明请参考下表:bash环境变量
在这里插入图片描述
3. 自定义环境变量(全局变量)
  设置环境变量
  如果想设置环境变量,就要在给变量赋值之后或设置变量时使用export命令,带-x选项的declare内置命令也可完成同样的功能。(注意:输出变量时不要在变量名前面加$)
  表 export命令和选项
  在这里插入图片描述
格式:

export    变量名=value              //第一种方法
变量名=value;export   变量名       //第二种方法。注意也可以一次导出多个变量名--> export   变量名 变量名 变量名
declare -x  变量名=value           //第三种方法
提示:以上为三种设置环境变量的方法
例:
export NAME=oldboy
declare  -x 

自定义环境变量生产环境java环境配置实例:

export JAVA_HOME=/opt/jdk
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
export TOMCAT_HOME=/opt/tomcat
export  PATH=$PATH:$TOMCAT_HOME/bin
放在:/etc/profile  或者 /etc/profile.d/下

4. 显示与取消环境变量

4.1通过echo命令打印环境变量

[root@yanwei-test1 scripts]# echo $HOME     #用户登录时进入的目录
/root
[root@yanwei-test1 scripts]# echo $UID      #当前用户的UID(用户标识)相当于id -u
0
[root@yanwei-test1 scripts]# echo $PWD     #当前工作目录的绝对路径名
/server/scripts  
[root@yanwei-test1 scripts]# echo $SHELL   #当前SHELL
/bin/bash
[root@yanwei-test1 scripts]# echo $USER
root
提示:在写shell脚本时可以直接使用上面的系统默认的环境变量

4.2 用env(printenv)或set显示默认的环境变量

[root@yanwei-test1 scripts]# env
TOMCAT_HOME=/opt/tomcat_8081
XDG_SESSION_ID=1277
HOSTNAME=yanwei-test1
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.0.157 49318 22
SSH_TTY=/dev/pts/0
USER=root
_=/usr/bin/env
OLDPWD=/root
提示:1.用set显示所有本地变量
     2.我们也可以自定义全局环境变量,

4.3 用unset取消本地变量和环境变量

[root@yanwei-test1 scripts]# export aa=ll
[root@yanwei-test1 scripts]# echo $aa
ll
[root@yanwei-test1 scripts]# unset aa   //只是临时生效,退出再登录就恢复了。
[root@yanwei-test1 scripts]# echo $aa
                                              #此处为输出的空行了

二、shell局部变量

1. 定义本地变量
  本地变量在用户当前的shell生产期的脚本中使用。例如,本地变量OLDBOY取值为ett098,这个值只在用户当前shell生存期中有意义。如果在shell中启动另一个进程或退出,本地变量OLDBOY值将无效。
1)普通字符串变量定义
  变量名=value
  变量名=‘value’
  变量名=“value”
shell中变量名的要求:一般是字母,数字,下划线组成。字母要开头,字母大写
  oldboy,oldboy123,oldboy_training
  例子:下面的例子会输出什么结果。

a=192.168.1.2-$a
b='192.168.1.2-$a'
c="192.168.1.2-$a"
echo "a=$a"
echo "b=$b"
echo "c=${c}"
提示:
 1) $c{c} 在这里等同。
需要在命令行实践以上内容。

答案:
  a=192.168.1.2-192.168.1.2
  b=192.168.1.2-$a
  c=192.168.1.2-192.168.1.2-192.168.1.2
提示:
  第一种定义a变量的方式是直接定义变量内容,内容一般为简单连续的数字、字符串、路劲名等。
  第二种定义b变量的方式是通过单引号定义变量。这个方式的特点是:输出变量时引号里是什么就输出什么,即使内容中有变量也会把变量名原样输出。此法比较适合于定义显示纯字符串。
  第三种定义c变量方式是通过双引号定义变量。这个方式的特点是:输出变量时引号里的变量会经过解析后输出该变量内容,而不是把引号中变量名原样输出,适合于字符串中附带有变量的内容的定义。
  习惯:数字不加引号,其他默认加双引号。

2. 定义变量单引号、双引号与不加引号
2.1有关单引号、双引号与不加引号的简要说明如下:
 单引号
  可以说是所见即所得:即将单引号内的内容原样输出,或者描述为单引号里面看到的是什么就会输出什么
 双引号
  把双引号内的内容输出出来;如果内容中有命令、变量等,会先把变量、命令解析出结果,然后在输出最终内容来。
 无引号
  把内容输出出来,会将含有空格的字符串视为一个整体输出,如果内容中有命令、变量等,会先把变量、命令解析出结果,然后在输出最终内容来,如果字符串中带有空格等特殊字符,则不能完整的输出,需要改加双引号,一般连续的字符串,数字,路径等可以不加任何引号,不过最好用双引号替代之。
   
2.2 把一个命令当做变量

//用 反引号 的方法
leaf@ubuntu:/$ cmd=`ls`     //把命令ls,赋给cmd
leaf@ubuntu:/$ echo $cmd    //输出cmd命令就相当于执行 ls命令
bin boot cdrom dev etc home initrd.img initrd.img.old lib lib32 lib64 
leaf@ubuntu:/$ 

//用 $() 的方法                
leaf@ubuntu:/$ cmd2=$(ls)    //把命令ls,赋给cmd2
leaf@ubuntu:/$ echo $cmd2    //输出cmd2命令就相当于执行 ls命令
bin boot cdrom dev etc home initrd.img initrd.img.old lib lib32 lib64 
leaf@ubuntu:/$ 

三、shell-的特殊变量-位置变量$0 $n $* $# $@详解

熟悉:$0  $n  $# 就可以。

1. 位置变量

$0   获取当前执行的shell脚本的文件名,包括路径
$n   获取当前执行的shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9,用大括号括起来${10}
$*   获取当前shell的所有参数,将所有的命令行参数视为单个字符串,相当于"$1$2$3"........注意与$#的区别
$#   获取当前shell命令行中的参数的总个数
$@   这个程序的所有参数"$1" "$2"  "$3"  ".....",这是将参数传递给其他程序的最佳方式,因为他会保留所有内嵌在每个参数里的任何空白。
提示:$*$@的区别

2.案例、演示(暂时只要熟悉下面案例的三个就可以)

范例1:演示$0
[root@1-241 scripts]# cat 0.sh
echo $0
[root@1-241 scripts]# sh 0.sh
0.sh
[root@1-241 scripts]# cd /root/
[root@1-241 ~]# sh /scripts/0.sh
/scripts/0.sh
 
范例2:演示$1$10的作用 (用于接命令行输入对应的第几个参数)
[root@1-241 scripts]# cat n.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}   # 对应获取,shell后面跟的参数,$1对应第一个,$2第二个,类推
[root@1-241 scripts]# sh n.sh `seq 10`  # 传入了10个参数  `seq 10`是传入1-10位数。
1 2 3 4 5 6 7 8 9 10                    # $n 输出 n对应的第几个参数。 
[root@1-241 scripts]# sh n.sh `seq 8`
1 2 3 4 5 6 7 8
[root@1-241 scripts]# sh n.sh `seq 12`
1 2 3 4 5 6 7 8 9 10
提示:
    在脚本里写入$1$10,在脚本执行传参,传入最大是10个参数,超过10个参数也不接收
 
范例3:演示$#的作用
[root@1-241 scripts]# cat n.sh
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
echo $#
[root@1-241 scripts]# sh n.sh 1 2 3 4 5
1 2 3 4 5
5
提示
$#,显示传入了多少个参数

四、shell-的特殊变量-进程状态变量$$ $! $? $_详解

熟悉:$?  $$ 就可以了。

1. 进程状态变量

$$    获取当前shell的进程号(pid)
$!    执行上一个指令的pid,上一个后台运行进程的进程号
$?    获取执行上一个指令的返回值(0为成功,非零为失败)
$_    在此之前执行的命令(上一个命令)或脚本的最后一个参数

举例(通过脚本举例,)

范例1:举例$$


[root@1-241 scripts]# echo $$   //获取当前shell的进程号(pid)
76037
[root@1-241 scripts]# ps -ef |grep 76037
root      76037  76035  0 05:26 pts/1    00:00:00 -bash
范例2:举例$$
[root@1-241 scripts]# cat 2.sh
echo $$ >/scripts/a.log
while true
do
   uptime
   sleep 2
done
[root@1-241 scripts]# cat a.log
76918
[root@1-241 scripts]# ps 76918
   PID TTY      STAT   TIME COMMAND
 76918 pts/1    S+     0:00 sh 2.sh

范例2:举例$?

[root@1-241 scripts]# jjklk
-bash: jjklk: command not found
[root@1-241 scripts]# echo $?
127
[root@1-241 scripts]# echo $?
0
提示:
$?:相当有用,是判断上一个命令是否执行成功
$?返回值参考 
 
0                  表示运行成功
2                  权限拒绝
1~125              表示运行失败,脚本命令、系统命令错误或参数传递错误
126                找到该命令了,但是无法执行
127                未找到要运行的命令
>128              命令被系统强制结束
提示:
在脚本调用,一般用exit 0,函数retrun  0。

举例(通过脚本举例,大家也可以一行行执行测试):

[root@1-241 scripts]# cat all.sh
echo '$0  获取当前执行的shell脚本的文件名:' $0
echo '$n  获取当前执行的shell脚本的第n个参数值,n=1..9:' '$1'=$1 '$2'=$2 "\$3=$3"
echo '$*  获取当前shell的所有参数 , $1 $2 $3 ....注意与$#的区别:' $*
echo '$#  获取当前shell命令行中参数的总个数:' $#
echo '$$  获取当前的shell的进程号(PID):' $$
sleep 2 &
echo '$! 执行上一个指令的PID:' $!
echo '$? 获取执行的上一个指令的返回值:' $?
echo '$@ 这个程序的所有参数 “$1” "$2" "$3" "...":' $@
echo '$_ 在此之前执行的命令或脚本的最后一个参数:' $_

执行结果:
$0  获取当前执行的shell脚本的文件名: all.sh
$n  获取当前执行的shell脚本的第n个参数值,n=1..9: $1=aa $2=bb $3=cc
$*  获取当前shell的所有参数 , $1 $2 $3 ....注意与$#的区别: aa bb cc
$#  获取当前shell命令行中参数的总个数: 3
$$  获取当前的shell的进程号(PID): 77147
$! 执行上一个指令的PID: 77148
$? 获取执行的上一个指令的返回值: 0
$@ 这个程序的所有参数 “$1"$2" "$3" "...": aa bb cc
$_ 在此之前执行的命令或脚本的最后一个参数: cc

五、shell-的特殊变量-难点理论

 1. $*$@的区别例子
     $* 将所有的命令行所有参数视为单个字符串,等同于“$1$2$3$@ 将命令行每个参数视为单独的字符串,等同于"$1" "$2" "$3"。
        这是将参数传递给其他程序的最佳方式,因为他会保留所有内嵌在每个参数里的任何空白。
        
 实例:
[root@1-241 scripts]# set -- "I am " handsome oldboy.       #传入三个参数
[root@1-241 scripts]# echo $#                               #现在有三个参数
3
[root@1-241 scripts]# for i in $*; do echo $i;done          #循环打印这些参数,用$*,无引号
I
am
handsome
oldboy.
[root@1-241 scripts]# for i in $@; do echo $i;done          #循环打印这些参数,用$@,无引号
I
am
handsome
oldboy.
[root@1-241 scripts]# for i ; do echo $i;done               #去掉in变量列表,相当于in “$@”
I am
handsome
oldboy.
[root@1-241 scripts]# for i in "$@"; do echo $i;done        #在有双引号的情况下,参数里引号内内容当做一个参数输出了,这才真正符合我们传入的参数需求,set  --  "I am" handsome oldboy.
I am
handsome
oldboy.
[root@1-241 scripts]# for i in "$*"; do echo $i;done          #加了双引号,$*表示一个字符串
I am handsome oldboy.
[root@1-241 scripts]# shift                                    #用shift去掉第一个参数
[root@1-241 scripts]# for i in "$@"; do echo $i;done         #再次打印只剩后面两个参数了
handsome
oldboy.
[root@1-241 scripts]# for i in "$*"; do echo $i;done
handsome oldboy.
[root@1-241 scripts]# for i ; do echo $i;done
handsome
oldboy.

六、shell的bash内部命令变量介绍与shift等

1. bash内部变量
有些内部命令在目录列表时是看不见的,他们有shell本身提供,常用的内部命令有:echo,eval,exec,export,readonly,read,shift,wait,exit和(.)

echo 变量名表
  将变量名表指定的变量显示到标准输出。

exalargs
  读入参数args,并将他们组合成一个新的命令,然后执行

exec命令参数
  当shell执行到exec语句时,不会去创建新的子进程,而是转去执行指定的命令,当指定的命令执行完时,该进程(也就是最初的shell)就终止了,所以shell程序中exec后面的语句将不在被执行。

exprot 变量名=value
  shell可以用exprot把它的变量向下带入子shell,从而让子进程继承父进程中的环境变量。但子shell不能用exprot把它的变量向上带入父shell

readonly 变量名
  只读变量用readonly显示所有只读变量

read 变量名表
  从标准输入读字符串,传给指定变量

shift 语句
  shift语句安装如下方式重新命名所有的位置参数变量,即$2 成为$1,$3成 2 在 程 序 中 每 使 用 一 次 s h i f t 语 句 , 都 使 所 有 的 位 置 参 数 依 次 向 左 移 动 一 个 位 置 , 并 使 位 置 参 数 2 在程序中每使用一次shift语句,都使所有的位置参数依次向左移动一个位置,并使位置参数 2使shift使使#减1,直到减到0为止。

2. shift语句使用举例:

[root@1-241 ~]# set -- "I am " handsome oldboy. 
[root@1-241 ~]# echo $#
3
[root@1-241 ~]# echo $1 $2 $3
I am handsome oldboy.
[root@1-241 ~]# echo $1
I am
[root@1-241 ~]# echo $2
handsome
[root@1-241 ~]# echo $3
oldboy.
[root@1-241 ~]# shift
[root@1-241 ~]# echo $1
handsome
[root@1-241 ~]# echo $2
oldboy.
[root@1-241 ~]# echo $3
 
[root@1-241 ~]# shift
[root@1-241 ~]# echo $1
oldboy.
[root@1-241 ~]# echo $2

七、shell-变量的字串应用技术

  1. 变量子串的常用操作
      常用操作如下表:
    在这里插入图片描述
    依次举例说明:
定义aa变量,内容为"I  am   scajy"
[root@1-241 script]# aa="I  am  scajy"
[root@1-241 script]# echo $aa
I am scajy

1、返回字符串aa变量字符串的长度

[root@1-241 ~]# echo ${#aa}
10

2、截取aa变量字符串从第2个字符之后开始取,默认取后面字符的全部,第2个字符不包含在内也可理解为删除前面的多少个字符

[root@1-241 ~]# echo ${aa:2}
am scajy

3、截取aa变量字符串从第2个字符之后开始取,取两个字符

[root@1-241 ~]# echo ${aa:2:2}
am
提示:类似cut -c 参数
[root@1-241 ~]# echo ${aa} |cut -c 1-4
I am
[root@1-241 ~]# echo ${aa} |cut -c 3-4
am

4、从变量aa开头开始删除最短匹配"I am“ 子串

[root@1-241 ~]# echo ${aa#I}
am scajy
[root@1-241 ~]# aa="I am scajy  I am"
[root@1-241 ~]# echo ${aa#I am}
scajy I am
[root@1-241 ~]# echo ${aa##I am}
scajy I am

5、从变量aa开头开始删除最短匹配"I am“ 子串

[root@1-241 ~]# echo ${aa##I am sc}
ajy I am

6、从变量aa结尾开始删除最短匹配 scajy子串

[root@1-241 ~]# echo ${aa%scajy}
I am

7、从变量aa结尾开始删除最长匹配 scajy子串

[root@1-241 ~]# aa="I am scajy scajy"
[root@1-241 ~]# echo ${aa%scajy}
I am scajy
[root@1-241 ~]# echo ${aa%%scajy}
I am scajy

8、使用520字符串,来代替变量aa第一个匹配的I字符串

[root@1-241 ~]# aa="I I am scajy"
[root@1-241 ~]# echo ${aa/I/520}
520 I am scajy

9、使用520字符串,来代替变量aa结尾开始匹配的I字符串

[root@1-241 ~]# aa="I I am scajy"
[root@1-241 ~]# echo ${aa/%scajy/520}
I I am 520

10、使用520 1314 字符串,来代替从变量aa开头开始匹配的I am字符串

[root@1-241 ~]# aa="I I am scajy"
[root@1-241 ~]# echo ${aa/I I am/520 1 314}
520 1 314 scajy

11、使用520 1314 字符串,来全部替换变量aa开头开始匹配的I am 字符串

[root@test-1 scripts]# aa="I am scajy,I am scajy,I am scajy,I am scajy "
[root@test-1 scripts]# echo ${aa//I am/520 1314}
520 1314 scajy,520 1314 scajy,520 1314 scajy,520 1314 scajy
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值