目录
变量和引用
一, 什么是变量
二, 根据数据类型分类
三, 根据作用域分类
1、环境变量
2、普通变量
四, 变量的定义
1、变量定义示例:变量名=变量值
2、位置参数和预定义变量
五, shell中的引用
六,变量的运算
变量和引用
一, 什么是变量
顾名思义,变量就是程序设计语言中的一个可以变化的量,当然,可以变化的是变量的值。几乎所 有的程序设计语言中都有定义变量,并且其涵义也大同小异。从本质上讲,变量就是在程序中保存用户 数据的一块内存空间,而变量名就是这块内存空间的地址。
在程序的执行过程中,保存数据的内存空间的内容可能会不断地发生变化,但是,代表内存地址的 变量名却保持不变。
环境变量全部用大写字母表示
变量:变量名=值(可不可以是一个表达式, 命令执行的结果)
二, 根据数据类型分类
Shell是一种动态类型语言和弱类型语言,即在Shell中,变量的数据类型毋需显示地声明,变量的数据类型会根据不同的操作有所变化。准确地讲,Shell中的变量是不分数据类型的,统一地按照字符串存储。但是根据变量的上下文环境,允许程序执行一些不同的操作,例如字符串的比较和整数的加减等等。
var_data=1 遇到有空格连接的字符串,空格以及空格后面的无法输出
var_data2='1' 单引号里面的内容原样输出
var_data3="1" 可以把空格打印出来,双引号整体输出
var_data4=`pwd` 反引号表示执行这条命令,获取这条命令的执行结果
Var_data5=$(pwd)
什么是弱类型语言、强类型语言?
强类型和弱类型主要是站在变量类型处理的角度进行分类的。强类型是指不允许隐式变量类型转换,弱类型则允许隐式类型转换。
强类型语言,当你定义一个变量是某个类型,如果不经过代码显式转换(强制转化)过,它就永远都是这个类型,如果把它当做其他类型来用,就会报错
弱类型语言,你想把这个变量当做什么类型来用,就当做什么类型来用,语言的解析器会自动(隐 式)转换。
比如:
C语言定义变量,int+变量名,实则前面的int就是给变量内存划分了等级,int定义整型所以空间里 只能存放整型,这就是强类型。php、C#和Python等都是强类型语言。
可以使用declare定义变量的类型:declare attribute variable
注:declare命令还可输出所有的变量、函数、整数和已经导出的变量
-p:显示所有变量的值
-i:将变量定义为整数,在之后就可以直接对表达式求值,结果只能是整数。如果求值
失败或者不是整 数,就设置为0。
-r:将变量声明为只读变量。只读变量不允许修改,也不允许删除。(也可使用readonly
定义只读变量)
-a:变量声明为数组变量。但这没有必要,所有变量都不必显示定义就可以用作数组。
事实上,在某 种意义上,似乎所有变量都是数组,而且赋值给没有下标的变量与
赋值给下标为0的数组元素相同。
-f:显示所有自定义函数,包括名称和函数体。
-x:将变量设置成环境变量。可使用+x将变量变成非环境变量
(环境变量必须使用declare -x 或者 export导出才称为环境变量 )
三,根据作用域分类
根据作用域可将变量分为环境变量(全局变量)和普通变量(局部变量)
1、环境变量
环境变量也可称为全局变量,可以在创建它们的shell及其派生出来的任意子进程shell中使用(su - 切换用户会读取新的环境变量),环境变量又可分为自定义环境变量和bash内置的环境变量。
命令行定义一个环境变量并用export命令导出,切换用户访问不到,新建连接也访问不到
(1)自定义环境变量
一般是指用export内置命令导出的变量,用于定义shell的运行环境,保证shell命令的正确执行。环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,即该环境变量只在当前 shell和子shell中有效。如果希望永久保存环境变量,可以在配置文件中设置。
①用户的环境变量配置(non-login shell)
~/.bash_profile或~/.bashrc
②全局环境变量的配置(login shell)
/etc/bashrc、/etc/profile文件或者/etc/profile.d目录(额外配置文件)中定义。
文件之间的联系:
在/etc/profile有一条: . /etc/bashrc -》 要去执行/etc/bashrc
(以". " 的方式执行不会产生子进程)
/etc/profile.d/*.sh . "$i" -> 也要去执行/etc/profile.d/*.sh的文件
在/etc/bashrc -> 会执行/etc/profile.d/*.sh文件
在~/.bash_profile中: . ~/.bashrc
在~/.bashrc中: . /etc/bashrc
1.如果我要配置一个只针对root用户的环境变量,应该配置在什么地方
~/.bash_profile或者~/.bashrc
2.如果我要配资一个针对所有用户的环境变量,应该配置在什么地方
/etc/profile或者/etc/bashrc 或者在/etc/profile.d目录中去定义.sh文件
定义环境变量的方式:
1. export mydata2=mydata2
2. mydata=mydata;export mydata
3. declare -x mydata3=mydata3
小练习:
1,进入到当前用户家目录下的配置文件中配置环境变量
[root@wangjingjing 0130]# vim ~/.bash_profile
mydata1=mydata1
export mydata1
export mydata2=mydata2
declare -x mydata3=mydata3
2,直接访问会出现访问不到,因为登录时,配置文件已经加载过
[root@wangjingjing 0130]# echo $mydata1
[root@wangjingjing 0130]# echo $mydata2
[root@wangjingjing 0130]# echo $mydata3
3,建立新的连接会重新加载配置文件可以直接访问到
[root@wangjingjing 0130]# echo $mydata1
mydata1
[root@wangjingjing 0130]# echo $mydata2
mydata2
[root@wangjingjing 0130]# echo $mydata3
mydata3
[root@wangjingjing 0130]#
4,Su - 会切换环境变量可以直接访问到
[root@wangjingjing 0130]# su -
[root@wangjingjing ~]# echo $mydata1
mydata1
[root@wangjingjing ~]# echo $mydata2
mydata2
[root@wangjingjing ~]# echo $mydata3
mydata3
5,在当前环境去访问(不产生子进程),source和.
[root@wangjingjing ~]# source ~/.bash_profile
[root@wangjingjing ~]# echo $mydata3
mydata3
[root@wangjingjing ~]# echo $mydata2
mydata2
[root@wangjingjing ~]# echo $mydata1
mydata1
[root@wangjingjing ~]#
注意:按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用 命令export导出。
有一些环境变量,比如HOME,PATH,SHELL,UID,USER等,在用户登录前就已经被/bin/login程序设置 好了,通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile 中。
(2)bash内置的环境变量
shell内置的环境变量是所有的shell程序都可以使用的变量。shell程序在运行时,都会接收一组变量 来确定登录用户名、命令路径、终端类型、登录目录等,这组变量就是环境变量。环境变量会影响到所 有的脚本的执行结果。
注:可使用env查看环境变量
1,HOME 用户主目录的路径名,是cd命令的默认参数
[root@wangjingjing ~]# echo $HOME
/root
[root@wangjingjing ~]# su redhat
[redhat@wangjingjing root]$ echo $HOME
/home/redhat
[redhat@wangjingjing root]$ exit
exit
[root@wangjingjing ~]#
2,IFS 定义shell使用的分隔符(默认是空行)
[root@wangjingjing ~]# echo $IFS
[root@wangjingjing ~]#
[root@wangjingjing ~]# echo "$IFS 123"
123
[root@wangjingjing ~]#
3,LOGNAME 当前的登录名
[root@wangjingjing ~]# echo $LOGNAME
root
[root@wangjingjing ~]# su redhat
[redhat@wangjingjing root]$ echo $LOGNAME
redhat
2、普通变量
普通变量也可称为局部变量,与全局变量相比,局部变量的使用范围较小,通常仅限于某个程序段访 问,例如函数内部。在Shell语言中,可以在函数内部通过local关键字定义局部变量,另外,函数的参数 也是局部变量。
四, 变量的定义
在Shell中,通常情况下用户可以直接使用变量,而毋需先进行定义,当用户第一次使用某个变量名 时,实际上就同时定义了这个变量,在变量的作用域内,用户都可以使用该变量。
1、变量定义示例:变量名=变量值
#!/bin/bash #定义变量a
a=1
#定义变量b
b="hello"
#定义变量c
c="hello world"
#定义备份路径
bak_dir=/data/backup
#把一个命令的结果赋值变量
变量名=`ls`
变量名=$(ls)
注意:
(1)“=”前后不能有空格
(2)字符串类型建议用引号括起来,尤其是特殊字符或有空格
引用变量:$变量名 或者${变量名}
[root@wangjingjing ~]# data=1
[root@wangjingjing ~]# echo $data
1
[root@wangjingjing ~]# echo ${data}
1
[root@wangjingjing ~]#
查看变量:echo $变量名,set(可查看所有变量:包括自定义变量和环境变量),env
显示全局变量, declare输出所有的变量、函数、整数和已经导出的变量。
[root@wangjingjing ~]# set | grep mydata
mydata1=mydata1
mydata2=mydata2
mydata3=mydata3
[root@wangjingjing ~]# env | grep mydata
mydata2=mydata2
mydata3=mydata3
mydata1=mydata1
[root@wangjingjing ~]# declare | grep mydata
mydata1=mydata1
mydata2=mydata2
mydata3=mydata3
[root@wangjingjing ~]#
取消变量:unset 变量名
[root@wangjingjing ~]# data=1
[root@wangjingjing ~]# echo $data
1
[root@wangjingjing ~]# unset data
[root@wangjingjing ~]# echo $data
[root@wangjingjing ~]#
作用范围:仅在当前shell中有效
注:可使用export指令将变量转换成环境变量
2、位置参数和预定义变量
许多情况下,Shell脚本都需要接收用户的输入,根据用户输入的参数来执行不同的操作。 从命令行传递给Shell脚本的参数又称为位置参数,Shell脚本会根据参数的位置使用不同的位置参数变量 读取它们的值。
练习:
建立一个脚本:args_script.sh
bash args_script.sh 传递6个参数
1.获取参数的个数
2.获取所有的参数
3.获取1,3,5这个三个位置的参数
4.获取脚本的名字
1,打开文件编辑并保存退出
[root@wangjingjing ~]# vim args_script.sh
echo "args count is $#"
echo "all args(@) are $@"
echo "all args(*) are $*"
echo "arg 1 is $1"
echo "arg 3 is $3"
echo "arg 5 is $5"
echo "script name is $0"
2,执行文件,传入参数
[root@wangjingjing ~]# bash args_script.sh 1 2 3 4 5 6
args count is 6
all args(@) are 1 2 3 4 5 6
all args(*) are 1 2 3 4 5 6
arg 1 is 1
arg 3 is 3
arg 5 is 5
script name is args_script.sh
$*和$@的区别示例: 整体 单独个体
[root@wangjingjing ~]# set -- 1 2 3 4
[root@wangjingjing ~]# for i in "$@";do echo $i;done;
1
2
3
4
[root@wangjingjing ~]# for i in "$*";do echo $i;done;
1 2 3 4
[root@wangjingjing ~]#
五, shell中的引用
在bash中有很多特殊字符,这些特殊字符就具有特殊含义。引用就是通知shell将这些特殊字符当作普通 字符来处理。
六,变量的运算
与其他的程序设计语言一样,shell也有很多运算符。
加法:
[root@wangjingjing ~]# data=$((1+2))
[root@wangjingjing ~]# echo $data
3
减法:
[root@wangjingjing ~]# data=$((1-2))
[root@wangjingjing ~]# echo $data
-1
乘法:
[root@wangjingjing ~]# data=$((1*2))
[root@wangjingjing ~]# echo $data
2
除法:
[root@wangjingjing ~]# data=$((1/2))
[root@wangjingjing ~]# echo $data
0
幂次方:
[root@wangjingjing ~]# data=$((2**2))
[root@wangjingjing ~]# echo $data
4
加等;其它等与之类似:
[root@wangjingjing ~]# data=1
[root@wangjingjing ~]# ((data+=1))
[root@wangjingjing ~]# echo $data
2
自增(++data) 自减与之相同:
[root@wangjingjing ~]# data=1
[root@wangjingjing ~]# ((data2=++data)) data加一后赋值给data2
[root@wangjingjing ~]# echo $data
2
[root@wangjingjing ~]# echo $data2
2
自增(data++):
[root@wangjingjing ~]# data=1
[root@wangjingjing ~]# ((data2=data++)) 把data赋值给data2后,data加一
[root@wangjingjing ~]# echo $data
2
[root@wangjingjing ~]# echo $data2
1
二进制
位运算(左移变大,右移变小)
左移:
[root@wangjingjing ~]# echo $((8<<2))
32
右移:
[root@wangjingjing ~]# echo $((8>>2))
2
与& :
[root@wangjingjing ~]# echo $((8&8))
8
或|:
[root@wangjingjing ~]# echo $((8|8))
8
异或^(相同为0,不同为1):
[root@wangjingjing ~]# echo $((8^8))
0
[root@wangjingjing ~]# echo $((1^2))
3
用作整数运算:(()) -> 双(())中变量不需要使用$
echo $(())
let: let 变量名=运算表达式
echo $变量名
expr: expr 1 + 1
expr 1 '+' 1
$[]: 使用: echo $[1+1]
declare: declare -i data=2+3
echo $data
用作小数的运算 :echo " 计算" | bc
1,(()) -> 双(())中变量不需要使用$
echo $(())
[root@wangjingjing ~]# echo $((1+1))
2
2, let: let 变量名=运算表达式
echo $变量名
[root@wangjingjing ~]# let data+1+1
[root@wangjingjing ~]# echo $data
2
3, expr: expr 1 + 1
expr 1 '+' 1
expr $num + $ num2
expr也可以检查两个值是否为数字,非数字无法运算,会报错
[root@wangjingjing ~]# expr 1 + 1
2
[root@wangjingjing ~]# expr 1 "+" 1
2
[root@wangjingjing ~]# num1=1
[root@wangjingjing ~]# num2=a
[root@wangjingjing ~]# expr $num1 + 1 &> /dev/null
[root@wangjingjing ~]# echo $?
0
[root@wangjingjing ~]# expr $num2 + 1 &> /dev/null
[root@wangjingjing ~]# echo $?
2
4,bc
echo " 表达式" | bc
[root@wangjingjing ~]# echo "1+1" | bc
2
直接执行bc命令是交互式的
5, $[]: 使用: echo $[1+1]
[root@wangjingjing ~]# echo $[1+4]
5
6,declare -I 变量=运算表达式
echo $变量
[root@wangjingjing ~]# declare -i data=8+9
[root@wangjingjing ~]# echo $data
17
练习:
定义两个变量:num1=10和num2=2
使用(()): 计算num1 + num2的值并输出
使用let: 计算num1 * num2的值输出
使用expr: 计算num1 对 num2执行或的位运算
使用$[]: 计算 num2的num1次方值
declare: 计算 num1 除以 num2的值
定义两个变量:num1=10和num2=2
[root@wangjingjing ~]# num1=10
[root@wangjingjing ~]# num2=2
1,使用(()): 计算num1 + num2的值并输出
[root@wangjingjing ~]# echo $((num1+num2))
2,使用let: 计算num1 * num2的值输出
[root@wangjingjing ~]# let data=num1*num2
[root@wangjingjing ~]# echo $data
3,使用expr: 计算num1 对 num2执行或的位运算
[root@wangjingjing ~]# expr $num1 "|" $num2
4,使用$[]: 计算 num2的num1次方值
[root@wangjingjing ~]# echo $[num2**num1]
5,declare: 计算 num1 除以 num2的值
[root@wangjingjing ~]# declare -i data=num1/num2
[root@wangjingjing ~]# echo $data
1,返回变量的内容
2,求字符串的长度
[root@wangjingjing ~]# echo ${#date}
3,截取字符串,截取3(输出不包括3)之后的字符串
[root@wangjingjing ~]# echo ${date:3}
4,从那个位置开始截取,以及截取的字符串的长度为多长
[root@wangjingjing ~]# echo ${date:2:2}
5,从最左边到最右边匹配到并删除最短的字符串
[root@wangjingjing ~]# echo ${data#*/}
6,从最左边到最右边匹配到并删除最长的字符串(最短作比较)
7,从最右到最左边匹配到并删除最短的字符串(最长作比较)
[root@wangjingjing ~]# echo ${data%/*}
8,从最右边到最右边匹配到并删除最长的字符串(最短作比较)
9,替换只替换第一个
10,替换所有,对原来的变量并没有改变
练习:
path=/data/data1/data2.txt
[root@wangjingjing ~]# path=/data/data1/data2.txt
去获取它所在的目录
[root@wangjingjing ~]# echo ${path%/*}
去获取文件的名字
[root@wangjingjing ~]# echo ${path##*/}