第二章 变量和引用

目录

[2.1. 深入认识变量](#2.1. 深入认识变量)

[2.1.1. 什么是变量](#2.1.1. 什么是变量)

[2.1.2. 变量的名称](#2.1.2. 变量的名称)

[2.1.3. 变量的类型](#2.1.3. 变量的类型)

[2.1.4. 变量的定义](#2.1.4. 变量的定义)

[2.1.5. 自定义变量](#2.1.5. 自定义变量)

[2.1.6. 环境变量](#2.1.6. 环境变量)

[2.1.7. 位置变量](#2.1.7. 位置变量)

[2.2. 变量赋值和作用域](#2.2. 变量赋值和作用域)

[2.2.1. 显示赋值:变量名=变量值](#2.2.1. 显示赋值:变量名=变量值)

[2.2.2. read 从键盘读入变量值](#2.2.2. read 从键盘读入变量值)

[2.2.3. 变量和引号](#2.2.3. 变量和引号)

[2.2.4. 变量的作用域](#2.2.4. 变量的作用域)


2.1. 深入认识变量

2.1.1. 什么是变量

变量是在程序中保存用户数据的一段内存存储空间,变量名是内存空间的首地址

2.1.2. 变量的名称

组成:字母、数字、下划线组成,不能以数字开头

变量名称的长度,shell没有明确规定,但是为了增加可读性,建议使用较短的、见名知意的名称命名规则

(1)首字符必须为字母:a-z,A-Z

(2)中间不能由空格,可以使用下划线(_)

(3)不能使用标点符号

(4)不能使用bash中关键字,输入help查看bash的保留字

(5)例:下面的变量名都是很好的选择

复制代码
[root@server ~]# JAVA_HOME=/usr/bin/jvm/jre-1.6.0-openjdk.x86_64
[root@server ~]# SUM=0
[root@server ~]# back_up=/root

2.1.3. 变量的类型

原则:shell是一种动态类型语言和弱类型语言,变量是不分数据类型的,统一都使用字符串存储,但根据变量的上下文环境,允许程序执行一些不同的操作,如:比较、整数加减

shell的变量数据类型

复制代码
[root@server ~]# vim test1.sh

#!/bin/bash

# 定义变量x,输入初始值123
x=123

# 变量x加1

let "x+=1"

# 输出变量x的值
echo "x=$x"

# 替换x中1的值为abc,并赋值给变量y
y=${x/1/abc}

# 使用declare -i 声明变量y为整型变量(-i 表示整型)
declare -i y

# 输出y的值
echo "y=$y"

[root@server ~]# bash test1.sh
x=124
y=abc24

2.1.4. 变量的定义

原则:直接使用,不需要变量声明

格式:变量名=变量的值

例:

复制代码
[root@server ~]# vim test2.sh

#!/bin/bash
# 定义变量a
a=1

# 定义变量b
b="hello"

# 定义变量c
c="hello world"

# 定义路径
bak_dir=/data/backup 14

前后不能收空格

复制代码
[root@server ~]# a= 3
bash: 3: command not found...
[root@server ~]# b =5
bash: b: command not found...

字符串类型建议使用双引好作为定界符引起,尤其是字符串中有空格

复制代码
[root@server ~]# stu_name=zhang san
bash: san: command not found...
[root@server ~]# stu_name="zhang san"
[root@server ~]# stu_name='zhang san'

2.1.5. 自定义变量

概念:上述以赋值形态形成的变量定义形式称为自定义变量

引用变量的值:

(1)$变量名

(2)${表达式或变量名}

(3)例:

复制代码
[root@server ~]# a=1024
[root@server ~]# echo $a
1024
[root@server ~]# echo ${a}
1024

查看变量

复制代码
[root@server ~]# set
[root@server ~]# declare

取消变量:unset 变量名

复制代码
[root@server ~]# a=256
[root@server ~]# echo $a
256
[root@server ~]# unset a
[root@server ~]# echo $a

作用范围:只在当前shell起效

2.1.6. 环境变量

环境变量又称为全局变量,可以在任意子shell生效,环境变量又分为自定义环境变量和bash内置的环境变

量,用户退出命令后改变量会丢失,若需要永久保存就必须写在文件中

定义环境变量

例:

复制代码
# 法1
export 环境变量=值

# 法2
变量名=值
export 变量名

# 法3
declare -x 变量名=值

复制代码
[root@server ~]# export back_dir1=/home/backup

[root@server ~]# NAME="zhang san"
[root@server ~]# export NAME

[root@server ~]# declare -x AGE=20

[root@server ~]# env # 显示当前用户的环境变量
[root@server ~]# printenv # 同上
[root@server ~]# export # 同上

注意:以上定义的环境变量都是临时的,重启后会失效,若要永久生效,则需要写入到配置文件中

对比:

复制代码
C语言  局部变量   全局变量
shell  自定义变量  环境变量

shell 环境变量存储的文件:

bash shell 初始化文件有: /etc/profile ~/.bash_profile ~/.bash_login ~/.profile

~/.bashrc /etc/bashrc

如图:

/etc/profile :存放一些全局(共有)变量,不管哪个用户,登录时都会读取该文件。通常设置一些

Shell 变量 PATH,USER,HOSTNAME HISTSIZE

~/.bash_profile :每个用户都可使用该文件输入专用于自己使用的 shell 信息 , 当用户登录时 , 该文件

仅仅执行一次,默认情况下 , 此文件通过脚本执行同目录下用户的 .bashrc 文件

~/.bashrc :该文件包含专用于你的 bash shell bash 信息 , 当登录时以及每次打开新的 shell , 该该

文件被读取

/etc/bashrc :为每一个运行 bash shell 的用户执行此文件 . bash shell 被打开时 , 该文件被读取

/etc/inputrc 文件为特定的情况处理键盘映射

执行顺序: /etc/profile-->/etc/profile.d/*.sh--> ~/.bash_profile -->/etc/bashrc-->~./.bashrc

结论:

(1)对于用户的环境变量设置,常见的是用户家目录下的.bashrc和.bash_profile

(2)对于全局环境变量设置,常见的文件有:/etc/profile /etc/bashrc /etc/profile.d 这三个配

置文件,常用方法是直接在 /etc/profile 文件中写入全局变量,如果想要在登陆后初始化或者

显示加载的内容,只需要把脚本文件放在 /etc/profile.d 文件下即可

2.1.7. 位置变量

概念:当一条命令或脚本执行时,后面可以跟多个参数,可以使用位置变量来表示该参数

复制代码
sh test1.sh hello world 123 456

当执行test1.sh 脚本时,第一个参数为hello到第四个参数可以使用特殊的符号表示,如:1 2 $3

......

常见的位置变量

复制代码
$0 : 脚本名
$1-$9 : 1-9个参数
${10} :10以上的参数需要大花括号括起
$* : 所有参数
$@ : 所有参数
$# : 参数个数
$$ : 当前进程的PID
$! : 上一个后台进程的PID
$? : 上一个命令的返回值状态码,0为成功

例:

复制代码
[root@server ~]# vim test3.sh
#!/bin/bash
echo "第2个位置参数是: $2"
echo "第1个位值参数是: $1"
echo "第4个位置参数是: $4"
echo "所有参数是: $*"
echo "所有参数是: $@"
echo "参数的个数是: $#"
echo "当前进程的PID值: $$"

[root@server ~]# bash test3.sh 1 2 3 4 5
第2个位置参数是: 2
第1个位值参数是: 1
第4个位置参数是: 4
所有参数是: 1 2 3 4 5
所有参数是: 1 2 3 4 5
参数的个数是: 5
当前进程的PID值: 1970
复制代码
[root@server ~]# vim test4.sh

[root@server ~]# bash test4.sh 孙小帅 18 123456@qq.com
name: 孙小帅
age: 18
E-mail:123456@qq.com

\* 与 @区别

复制代码
当$* 和 $ @没有被引用的时候,它们确实没有什么区别,都会把位置参数当成一个个体, "$*"会把所有位置参
数当成一个整体(或者说当成一个单词),如果没有位置参数,则"$* "为空,如果有两个位置参数并且IFS为空
格时,"$*"相当于"$1 $2"

"$@"会把所有位置参数当成一个单独的字段,如果没有位置参数($#为0),则"$@"展开为空(不是空字符串,
而是空列表),如果存在一个位置参数,则"$@"相当于"$1",如果有两个参数,则"$@"相当于"$1" "$2"等等

[root@server ~]# set -- I am test command
[root@server ~]# for i in "$@"; do echo $i; done
I
am
test
command
[root@server ~]# for i in "$*"; do echo $i; done
I am test command

2.2. 变量赋值和作用域

2.2.1. 显示赋值:变量名=变量值

例:

复制代码
ip1=192.168.1.251
school="Peking University"
today1=`date +%F`  # 注意为反引号``
today2=$(date +%F)

2.2.2. read 从键盘读入变量值

read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量

格式: read - 参数 变量名

参数

(1)-p "提示语句:" 屏幕打印出一行提示语句。

(2)-n数字:当输入的字符数目达到预定数目时,自动退出,并将输入的数据赋值给变量,如:-n1 , 只

要接受到一个字符就退出。只要按下一个字符进行回答,read命令立即接受输入并将其传给变量。无需按回车键

(3)-t 等待时间 :计时输入,使用read命令存在着潜在危险。脚本很可能会停下来一直等待用户的输

入。如果无论是否输入数据脚本都必须继续执行,那么可以使用 -t 选项指定一个计时器。 -t 选项指定

read 命令等待输入的秒数。当计时满时, read 命令返回一个非零退出状态

(4)-s : 关闭回显,使read命令中输入的数据不显示在监视器上(实际上,数据是显示的,只是read命

令将文本颜色设置成与背景相同的颜色)

(5)常用格式:

复制代码
read 变量名
read -p "提示信息:" 变量名

例:

复制代码
[root@server ~]# read -p "Enter Numbers: " num
Enter Numbers: 9527
[root@server ~]# echo $num
9527
[root@server ~]# read -t 3 n1 # 不要输入内容,等待3秒后自动结束输入
[root@server ~]# read -s -p "Enter your password: " passw
Enter your password: [root@server ~]# echo $passw
123456
[root@server ~]# echo $REPLY
[root@server ~]# read
100
[root@server ~]# echo $REPLY # 当输入时没有指定变量接收,会默认存储到REPLY变量中
100
# 一次性输入多个变量的值
[root@server ~]# read t1 t2
12 35
[root@server ~]# echo $t1 $t2
12 35

面试题:总结4中赋值方式

复制代码
1.直接赋值:name="li si"
2.read命令: read name
3.使用位置参数($1 $2 $3...) : name=$1
4.命令输入:name=$(whoami)

2.2.3. 变量和引号

双引号:除了$ 、单引号、反引号、反斜线之外,其它被引起的内容保持字面意思

单引号:所有字符保持字面意思

反引号:被引起的字符串转为shell命令

反斜线:转义符(\),屏蔽后面字符的特殊含义

2.2.4. 变量的作用域

全局变量:全局变量定义在脚本中,也可以定义在函数中,作用范围:从定义的开始处到shell脚本结束或

者被显示的去除

例:

复制代码
[root@server ~]# vim test5.sh

#!/bin/bash

func() # 定义函数
{
    echo "$v1"
    v1=200
}
v1=100
func
echo "$v1"

[root@server ~]# bash test5.sh
100
200

函数内部定义全局变量

复制代码
# 上例修改
[root@server ~]# vim test5.sh

#!/bin/bash
func() # 定义函数
{
    v2=200
}
func
echo "$v2"

[root@server ~]# bash test5.sh
200

局部变量:范围更小,仅限于某个程序段中,如:函数、shell等,通过local关键字定义,注意:函数的参

数也是局部变量

复制代码
# 上例修改
[root@server ~]# vim test5.sh
#!/bin/bash
func() # 定义函数
{
    local v3=200 # 使用local关键字声明为局部变量
}
func
echo "$v3"
[root@server ~]# bash test5.sh

全局变量和局部变量区别

复制代码
# 上例修改
[root@server ~]# vim test5.sh

#!/bin/bash
func()
{
#输出全局变量v1的值
echo "global variable v1 is $v1"
#定义局部变量v1
local v1=2
#输出局部变量v1的值
echo "local variable v1 is $v1"
}

#定义全局变量v1
v1=1
#调用函数
func
#输出全局变量v1的值
echo "global variable v1 is $v1"

2.2.5. 变量的运算

运算符与命令

示例1:

复制代码
[root@server ~]# expr 1 + 1 # 注意+左右必须要有空格
2
[root@server ~]# expr 1+1 # 否则原样显示
1+1
[root@server ~]# a=1
[root@server ~]# b=2
[root@server ~]# expr $a + $b # 支持变量
3

[root@server ~]# let num=1+2 # let+echo 等价于expr
[root@server ~]# echo $num
3
[root@server ~]# let num=1 + 2 # 注意let中运算符左右不能由空格
-bash: let: +:语法错误: 需要操作数 (错误符号是 "+")


[root@server ~]# echo $((1+2))
3
[root@server ~]# echo $((5%3))
2
[root@server ~]# echo $((3%5))
3
[root@server ~]# echo $((1-5))
-4
[root@server ~]# echo $((2 * 5)) # 可以有空格
10
[root@server ~]# echo $((5.2-5)) # 只支持整数运算
-bash: 5.2-5:语法错误: 无效的算术运算符 (错误符号是 ".2-5")


[root@server ~]# echo $[2+3] # [] 等价于 (())
5
[root@server ~]# echo $[2.5+3] # # 只支持整数运算
-bash: 2.5+3:语法错误: 无效的算术运算符 (错误符号是 ".5+3")


[root@server ~]# bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software
Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1.1+2
3.1
2.5-3.9
-1.4
1.5>4
0
5>3
1
quit # 退出交互模式
# 不进入交互模式直接使用,bc需要放在最后
[root@server ~]# echo "scale=3;11/3" | bc
3.666
# scale=3 表示保留运算精度

示例2 :

复制代码
# 返回变量长度
[root@server ~]# str1="hello world"
[root@server ~]# echo ${#str1}
11
复制代码
# 变量截取
[root@server ~]# echo ${str1:0:3} # 从左边第1个字符开始截取3个
hel
[root@server ~]# echo ${str1::3} # 可以省略起始0
hel
[root@server ~]# echo ${str1:1} # 从下标1开始截取到尾部
ello world
[root@server ~]# echo ${str1:0-1:1} # 从右边第一个字符开始截取1个,左边第一个为0,右边第一个为0-1
d
[root@server ~]# echo ${str1:0-5} # 从右边第5个开始截取到尾部
world
[root@server ~]# echo ${str1: -5} # 使用空格替代0,同上
world
[root@server ~]# echo ${str1:-5} # 没有空格表示提取整串
hello world
复制代码
# 使用%截取,删除右边字符,保留左边字符
[root@server ~]# filename=testfile.tar
[root@server ~]# file=${filename%.*} # %.表示从右边开始检索第一次出现. 之后删除.右侧的内容,保留左边内容,用于对文件名去掉扩展名
[root@server ~]# echo $file
testfile

[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url%%:*} # %%: 表示从右边开始检索最后一次出现的: 之后删除:右侧的内容,保留左边内容
[root@server ~]# echo $ul1
http
                       
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url#*.} # #*.表示左向右遍历,删除第一次出现的.左侧内容
[root@server ~]# echo $ul1
baidu.com/index.html
                       
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url%/*}
[root@server ~]# echo $ul1
http://www.baidu.com
[root@server ~]# url=http://www.baidu.com/index.html
[root@server ~]# ul1=${url##*/}
[root@server ~]# echo $ul1
index.html

特殊扩展

- 示例:如果 parameter 变量值为空或未赋值,则返回 word 字符串的值,注意: parameter 变量值不变

复制代码
[root@server ~]# echo $var1

[root@server ~]# var2=${var1:-hello}
[root@server ~]# echo $var2
hello

-示例:如果parameter变量有值,则返回parameter变量值

复制代码
[root@server ~]# var2=${var1:-world}
[root@server ~]# echo $var2
hello

=示例:如果parameter变量有值,则返回parameter变量值

复制代码
[root@server ~]# unset var1 var2
[root@server ~]# var1=hello
[root@server ~]# var2=${var1:=world}
[root@server ~]# echo $var2
hello

?示例:如果parameter变量值为空或未赋值,则word字符串会作为标准错误输出,否则输出变量的值

复制代码
[root@server ~]# unset var1 var2
[root@server ~]# var2=${var1:?world}
-bash: var1: world # 标准错误输出
[root@server ~]# unset var1 var2
[root@server ~]# var1=hello
[root@server ~]# var2=${var1:?world}
[root@server ~]# echo $var2
hello

+示例:如果parameter变量值为空或未赋值,则什么都不做,否则word字符串将替代变量的值

复制代码
[root@server ~]# unset var1 var2
[root@server ~]# var2=${var1:+world}
[root@server ~]# echo $var2

[root@server ~]# unset var1 var2
[root@server ~]# var1=hello
[root@server ~]# var2=${var1:+world}
[root@server ~]# echo $var1 $var2
hello world

面试题:删除7天前的过期备份数据

复制代码
#!/bin/bash
find ${path:-/tmp} -name "*.tar.gz" -type f mtime +7 | xargs rm -f

# find为查找文件命令
# ${path:-/tmp} :表示如果没有定义path则使用/tmp替代
# find不支持| 使用xargs命令表示管道符进行数据转换
相关推荐
XIAOHEZIcode1 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220702 天前
如何搭建本地yum源(上)
运维
大树885 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠5 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质5 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工5 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智5 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_5 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉5 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造
程序猿阿伟5 天前
《Chrome离线扩展安装的底层逻辑与场景落地指南》
服务器·网络·chrome