目录
变量和引用
2.1.深入认识变量
2.1.1.什么是变量
变量是在程序中保存用户数据的一段内存存储空间,变量名是内存空间的首地址
变量三要素:名称、类型、值
2.1.2.变量的名称
组成: 字母、数字、下划线组成,不能以数字开头
变量名称的长度,shell没有明确规定,但是为了增加可读性,建议使用较短的、见名知意的名称命名则:
首字符必须为字母:a-z,A-Z
中间不能由空格,可以使用下划线 ()
不能使用标点符号
不能使用bash中关键字,输入help查看bash的保留字例:下面的变量名都是很好的选择
[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
x=123let x+=1
echo "x=$x"
[root@server ~]# bash test1.shx=124
2.1.4.变量的定义
原则:直接使用,不需要变量声明。格式:变量名=变量的值
例:[root@server ~]# vim test2.sh
a=1
b="hello"
c="hello world"
bak_dir=/mnt
[root@server ~]# bash test2.sh前后不能收空格
[root@server ~]# a= 3
bash: 3: command not found...[root@server ~]# b =5
bash: b: command not found...
字符串类型建议使用双引好作为定界符引起,尤其是字符串中有空格
[root@server ~]# stu_name=zhangsanbash: san: command not found...
[root@server ~]# stu_name="zhang san'
[root@server ~]# stu_name='zhang san
2.1.5自定义变量
概念:上述以赋值形态形成的变量定义形式称为自定义变量
引用变量的值
$变量名
${表达式或变量名)例:
[root@server ~]# a=1024
[root@server ~]# echo $a
1024
[root@server ~]# echo {$a}
{1024}
[root@server ~]# echo ${a}
1024查看变量
[root@server ~]# set |more |grep a=
2.1.6.环境变量(全局变量)
环境变量又称为全局变量,可以在任意子shell生效,环境变量又分为自定义环境变量和bash内置的环境变量,用户退出命令后改变量会丢失,若需要永久保存就必须写在文件中
定义环境变量
例:
bash自带的全局变量:
[root@server ~]# vim /etc/profile
[root@server ~]# echo $PATH
/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
[root@server ~]# echo $SHELL
/bin/bash自定义全局变量 :
法一:export 环境变量=值
[root@server ~]# export back_dir1=/home/fox
法二:
变量名=值
export 变量名
[root@server ~]# NAME=zhangsan
[root@server ~]# export NAME
法三:declare -X 变量名=值
[root@server ~]# declare -x AGE=20
显示全局变量:
[root@server ~]# env
[root@server ~]# printenv
[root@server ~]# export
注意:以上三者效果一样
注意:以上定义的环境变量都是临时的,重启后会失效,若要永久生效,则需要写入到配置文件中
2.1.7 shell 环境变量存储的文件
bash shell 初始化文件有: /etc/profile、 ~/.bash_profil、 ~/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
bash内置环境变量
影响所有的脚本的执行结果。
变量 说明 PATH 命令的搜索路径,以冒号作为分隔符 HOME 用户的家目录的路径,是cd命令的默认参数 COLUMNS 命令行编辑模式下可使用命令的长度 HISTFILE 命令历史的文件路径 HISTFILESIZE 命令历史中包含的最大行数 HISTSIZE history命令输出的记录数 LOGNAME 当前用户的名字 SHELL 当前使用的shell PWD 当前的工作目录
2.1.8.位置变量
概念:当一条命令或脚本执行时,后面可以跟多个参数,可以使用位置变量来表示该参数
bash testl.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.shecho "第一个位置的参数是:$1" echo "第二个位置的参数是:$2" echo "第四个位置的参数的:$4" echo "所有参数是:$*" echo "所有参数的:$@" echo "参数个数是:$#" echo "当前脚本的进程PID值:$$" echo "当前脚本的文件名$0"
[root@server ~]# bash test3.sh a b c d e f g
$* 与 $@区别:
当S* 和 S @没有被引用的时候,它们确实没有什么区别,都会把位置参数当成一个个体,"$*"会把所有位置参数当成一个整体(或者说当成一个单词),如果没有位置参数,则"S* "为空,如果有两个位置参数并且IFS为空格时,"$*"相当于"$1 $2"
"$@"会把所有位置参数当成一个单独的字段,如果没有位置参数 (S#为0),侧”S@"展开为空(不是空字符串,而是空列表),如果存在一个位置参数,则"S@"相当于"S1",如果有两个参数,则"S@"相当于"$1" "$2"等等
declare命令
declare为shell指令,在第一种语法中可用来声明变量并设置变量的属性([rix]即为变量的属性),在第二种语法中可用来显示shell函数。若不加上任何参数,则会显示全部的shell变量与函数(与执行set指令的效果相同)。
语法:declare [+/-][rxi][变量名称=设置值] 或 declare -f
+/- "-"可用来指定变量的属性,"+"则是取消变量所设的属性。
-f 仅显示函数。
r 将变量设置为只读。
x 指定的变量会成为环境变量,可供shell以外的程序来使用。
i [设置值]可以是数值,字符串或运算式。
声明整数型变量
# declare -i ab //声明整数型变量 # ab=56 //改变变量内容 # echo $ab //显示变量内容 56改变变量属性
# declare -i ef //声明整数型变量 # ef=1 //变量赋值(整数值) # echo $ef //显示变量内容 1 # ef="wer" //变量赋值(文本值) # echo $ef 0 # declare +i ef //取消变量属性 # ef="wer" # echo $ef wer设置变量只读
# declare -r ab //设置变量为只读 # ab=88 //改变变量内容 -bash: ab: 只读变量 # echo $ab //显示变量内容 56声明数组变量
# declare -a cd='([0]="a" [1]="b" [2]="c")' //声明数组变量 # echo ${cd[1]} b //显示变量内容 # echo ${cd[@]} //显示整个数组变量内容 a b c显示函数
# declare -f command_not_found_handle () { if [ -x /usr/lib/command-not-found ]; then /usr/bin/python /usr/lib/command-not-found -- $1; return $?; else if [ -x /usr/share/command-not-found ]; then /usr/bin/python /usr/share/command-not-found -- $1; return $?; else return 127; fi; fi }
2.2.变量赋值和作用域
2.2.1.显示赋值:变量名=变量值
[root@server ~]# ip1=192.168.17.128
[root@server ~]# school="PeKing University"
[root@server ~]# today1=`date +%F` [root@server ~]# today2=$(date +%F) [root@server ~]# echo $ip1
192.168.17.128
[root@server ~]# echo $school
PeKing University
[root@server ~]# echo $today1
2023-12-04
[root@server ~]# echo $today2
2023-12-04 # 由此得出 ` ` 等于 $()
2.2.2.read 从键盘读入变量值
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
格式: read -参数 变量名
参数:
-p“提示语句:” 屏幕打印出一行提示语句
-n数字:当输入的字符数目达到预定数目时,自动退出,并将输入的数据赋值给变量,如:n1,只要接受到一个字符就退出。只要按下一个字符进行回答,read命令立即接受输入并将其传给变量。无需按回车键
-t 等待时间:计时输入,使用read命令存在着潜在危险。脚本很可能会停下来一直等待用户的输入。如果无论是否输入数据脚本都必须继续执行,那么可以使用-t选项指定一个计时器。t选项指定read命令等待输入的秒数。当计时满时,read命令返回一个非零退出状态关闭回显,使read命令中输入的数据不显示在监视器上 (实际上,数据是显示的,只是
-s:read命令将文本颜色设置成与背景相同的颜色)
常用格式:
read 变量名
read -p “提示信息:” 变量名例:
参数 -p:
[root@server ~]# read -p "Enter Numbers: " num
Enter Numbers: 123
[root@server ~]# echo $num
123
[root@server ~]# read -p "enter char (y/n):" num
enter char (y/n):y
[root@server ~]# echo $num
y参数 -t:
[root@server ~]# read -t 3 n1 # 等待三秒自动结束命令
[root@server ~]# read -s -p "请输入密码:" passwd
请输入密码:[root@server ~]# # 此处已经输入密码但默认不回显(无换行功能)当read后没有变量接收值时:
[root@server ~]# read
200
[root@server ~]# echo $REPLY # 当输入时没有变量接收则会存储到环境变量REPLY中
200一次性输入多个值:
[root@server ~]# read t1 t2 t3
132 344 "hehe"
[root@server ~]# echo $t1 $t2 $t3
132 344 "hehe"
[root@server ~]# read t1 t2 t3
132 344 hehe
[root@server ~]# echo $t1 $t2 $t3
132 344 hehe # 由此可得每一个值之间只需用空格隔开
2.2.3.变量和引号
双引号:(" ") 除了$、单引号、反引号、反斜线之外,其它被引起的内容保持字面意思
单引号:(' ') 所有字符保持字面意思,单引号括起来的字符都作为普通字符出现 .(少用)
反引号: (``)。反引号括起来的字串被Shell解释为命令,在执行时,Shell首先执行该命令,并以它的标准输出结果取代整个反引号(包括两个反引号)部分
反斜线: 转义符,屏蔽后面字符的特殊含义\n: 换行
\t: 制表符
\f: 分页(换页)
\r: 回车但不换行
\b: 退格
\\: 输出一个\
2.2.4.变量的作用域
全局变量:全局变量定义在脚本中,也可以定义在函数中,
作用范围: 从定义的开始处到shel脚本结束或者被显示的去除
局部变量:范围更小,仅限于某个程序段中,如: 函数、shell等,通过local关键字定义,注意函数的参数也是局部变量
全局变量和局部变量区别:
[root@server ~]# vim test5.sh
func() { #输出全局变量v1的值 echo "global variable vl is $v1" #定义局部变量v1 local v1=2 #输出局部变量v1的值 echo "local variable vl is $v1" } #定义全局变量v1 v1=1 #调用函数 func #输出全局变量v1的值 echo "global variable v1 is $v1!
[root@server ~]# bash test5.sh
global variable vl is 1
local variable vl is 2
global variable v1 is 1!
2.2.5.变量的运算
运算符与命令:
Shell 中常见的算术运算符号
算术运算符 意义(*表示常用) +、- 加法(或正号)、减法(或负号)* *、/、%
乘法、除法、取余(取模)* ** 幂运算* ++、-- 增加及减少,可前置也可放在变量结尾* !、&&、|| 逻辑非(取反)、逻辑与(and)、逻辑或(or)* <、 <=、 >、>= 比较符号(小于、小于等于、大于、大于等于) ==、!=、= 比较符号(相等、不相等,对于字符串“=”也可以表示相当于)* <<、>> 向左移位、向右移位 ~、|、&、^ 按位取反、按位异或、按位与、按位或 = 、+=、- =、*=、/=、%=
赋值运算符,例如a+=1相当于a=a+l,a-=1相当于a=a-1*
Shell 中常见的算术运算命令
运算操作符与运算命令 意义 (()) 用于整数运算的常用运算符,效率很高 let 用于整数运算,类似于“(0)” expr 可用于整数运算,但还有很多其他的额外功能(自带输出功能 ) bc Linux下的一个计算器程序(适合整数及小数运算) $[] 用于整数运算 awk awk 既可以用于整数运算,也可以用于小数运算 declare 定义变量值和属性,-i 参数可以用于定义整形变量,做运算
例一:数字型
expr:
[root@server ~]# expr 1 + 1 # 缺点:运算符之间必须有空格
2[root@server ~]# expr $a + $b # 需要加$
3(()):
[root@server ~]# a=2
[root@server ~]# b=6
[root@server ~]# echo $((1+2))
3
[root@server ~]# echo $((a+b))
8[root@server ~]# echo $((5/2))
2
[root@server ~]# echo $((5%2))
1[root@server ~]# echo $((2.6+2)) # 由此可见(())不支持小数
-bash: 2.6+2:语法错误: 无效的算术运算符 (错误符号是 ".6+2")
[root@server ~]# echo $[2.6+2]
-bash: 2.6+2:语法错误: 无效的算术运算符 (错误符号是 ".6+2")bc:(内置计算器)
[root@server ~]# bc # 进入计算器 # 注意:需使用quit 退出交互模式
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+2 3 2-5 -3 6/2 3 1.5+2.3\ 3.8 5>3 1 3>5 0 quit # 退出交互模式
Shell 变量子串说明
表达式 说明 ${parameter} 返回变量 $parameter 的内容 ${#parameter} 返回变量 $parameter 内容的长度(按字符)也适用于特殊变量 ${parameter:offset} 在变量 ${parameter}中,从位置 offset 之后开始提取子串到结尾 ${parameter:offset:length} 在变量 ${parameter}中,从位置offset 之后开始提取长度为 length的子串 ${parameter#word} 从变量 ${parameter} 开头开始删除,最短匹配的 word 子串 ${parameter##word} 从变量${parameter} 开头开始删除,最长匹配的 word 子串 ${parameter%word} 从变量${parameter} 结尾开始删除,最短匹配的 word 子串 ${parameter%%word} 从变量${parameter} 结尾开始删除,最长匹配的 word 子串 ${parameter/pattern/string} 使用string 代替第一个匹配的 pattern ${parameter//pattern/string} 使用 string 代替所有匹配的 pattern
例二:字符串型
使用“:”截取字符串 # 格式:${字符串:start :end}
返回变量长度
[root@localhost ~]# str1="hello world"
[root@localhost ~]# echo ${#str1}
11
变量截取 切片 :
指定起始位置,一直到结束
[root@localhost ~]# echo ${str1:1}
ello world
指定长度,不指定起始位置默认从开头开始
[root@localhost ~]# echo ${str1::3}
hel
指定起始位置和长度
[root@localhost ~]# echo ${str1:1:3}
ell
从右边第几个字符开始,及字符的个数
[root@localhost ~]# echo ${str1:0-1:1}
d
输出右边的几个字符
[root@localhost ~]# echo ${str1:0-5}
world
[root@localhost ~]# echo ${str1: -5}
world
使用%截取字符串,含义: 删除右边字符,保留左边字符
删除字符串: #
// 获取后缀名tar.gz
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename#*.} # 开头最短匹配的
[root@localhost ~]# echo $file
tar.gz// 获取后缀名gz
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename##*.} # 开头最长匹配
[root@localhost ~]# echo $file
gz//截取testfile.tar
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename%.*} # 结尾最短匹配的
[root@localhost ~]# echo $file
testfile.tar//截取testfile
[root@localhost ~]# filename=testfile.tar.gz
[root@localhost ~]# file=${filename%%.*} # 结尾最长匹配
[root@localhost ~]# echo $file
testfile
//替换
[root@localhost ~]# echo ${str/is/IS} # 代替第一个匹配
thIS is haha
[root@localhost ~]# echo ${str//is/IS} # 代替所有匹配
thIS IS haha
2.2.6.shell特殊扩展
Shell 的特殊扩展变量说明
表达式 说明 ${parameter:-word} 如果 parameter 的变量值为空或未赋值,则会返回 word 字符串并代变量的值
用途:如果变量未定义,则返回备用的值,防止变量为空值或因未定义而导致异常
${parameter:=word} 如果 parameter 的变量值为空或未赋值,则设置这个变量值为 word,并返回其值位置变量和特殊变量不适用
用途:基本同上一个Sparameter:-word},但该变量又额外给 parameter 变量赋值了
${parameter:?word} 如果 parameter 变量值为空或未赋值,那么word 字符串将被作为标准错误输出,否则输出变量的值。
用途:用于捕提由于变量未定义而导致的错误,并退出程序${parameter:+word} 如果 parameter 变量值为空或未赋值,则什么都不做,否则word 字符串将替代变量的值
例:
-示例:用法1,如果parameter变量值为空或未赋值,则返回word字符串代替变量的值
//变量未赋值,输出为空。 (冒号可有可无) --------无值临时赋值
[root@localhost ~]# echo $var1[root@localhost ~]# var2=${var1:-hello}
[root@localhost ~]# echo $var2
hello
-示例:用法2,如果parameter变量值有值,则变量返回parameter变量的值
[root@localhost ~]# var1="hello"
[root@localhost ~]# echo $var1
hello
[root@localhost ~]# var2=${var1:-world}
[root@localhost ~]# echo $var2
hello=示例:用法1,如果parameter变量值为空或未赋值,则返回word字符串给变量赋值
注意和-,不同点在于-var1没有赋值,=将word赋值刚给var1 ---无值永久赋值
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var2=${var1:=world}
[root@localhost ~]# echo $var2
world
[root@localhost ~]# echo $var1
world=示例:用法2,如果parameter变量值有值,则返回parameter变量的值
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1=hello
[root@localhost ~]# var2=${var1:=world}
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# echo $var1
hello?示例:
{parameter:?word}的作用是: 如果 parameter 变量值为空或未赋值, 那么 word 字符
串将被作为标准错误输出, 否则输出变量的值。
[root@localhost ~]# unset var1 var2
[root@localhost ~]# var2=${var1:?world} ---无值作为提示信息报错,临时赋值
-bash: var1: world expr length $var1[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1=hello
[root@localhost ~]# var2=${var1:?world}
[root@localhost ~]# echo $var2
hello
[root@localhost ~]# echo $var1
hello+示例:
${parameter:+word}的作用是: 如果 parameter 变量值为空或未赋值, 则什么都不
做, 否则 word 字符串将替代变量的值
[root@localhost ~]# unset var1 ---无值什么都不做,有值则替换,临时替换
[root@localhost ~]# var2=${var1:+world}
[root@localhost ~]# echo $var2[root@localhost ~]# unset var1 var2
[root@localhost ~]# var1=hello
[root@localhost ~]# var2=${var1:+world}
[root@localhost ~]# echo $var2
world
[root@localhost ~]# echo $var1
helloshell特殊扩展应用案例:
删除7天前的过期数据备份。
[root@localhost ~]# cat del.sh | 字符 -exec |xargs 参数
find ${path:-/tmp} -name "*.bak" -type f -mtime +7 | xargs rm -f
如果没有定义path值,事先脚本中也没有设置变量:
[root@localhost ~]# cat del2.sh
find ${path} -name "*.tar.gz" -type f -mtime +7 | xargs rm -f
这样就不会删除指定目录,而是删除脚本运行目录中的文件。