定义和使用变量
脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则。
shell中如果没有声明数据类型,默认为字符串类型
在 Bash shell 中,默认情况下,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。除非使用declare声明变量类型
定义变量时不加美元符号(或者说给变量赋值时不加美元符号)
使用变量时要加美元符号
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界。推荐给所有变量加上花括号{ }
,这是个良好的编程习惯。
已定义的变量,可以被重新定义,重定义也不加美元符号(给变量赋值就是定义变量?)
变量赋值时,变量名和等号以及值之间不能有空格
在数学计算命令(())中也可以定义和使用变量,并且在(())中使用变量时不需要加$
your_name="tom" //定义变量,不加美元符号,变量名和等号之间不能有空格 echo $your_name //使用变量 your_name="alibaba" //重新定义,不加美元符号
echo $your_name
your_name="qinjx" echo $your_name //变量名外不加{} echo ${your_name} //变量名外加{},推荐使用
for skill in Ada Coffe Action Java; do echo "I am good at ${skill}Script" //变量名外加{},有效识别变量的边界
done
变量命名
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 不能使用bash里的关键字(可用bash --help命令查看保留关键字)
有效的 Shell 变量名示例
RUNOOB
LD_LIBRARY_PATH
_var
var2
无效的变量命名
?var=123 //不能使用了英文字母,数字和下划线以外的字符
user*name=runoob
1name=runoob //不能使用数字开头
变量的值
如果 变量的值value 不包含任何空白符(例如空格、Tab 缩进等),那么可以不使用引号;
如果 value 包含了空白符,那么就必须使用引号包围起来。
使用单引号和使用双引号也是有区别的
以单引号' '
包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。
以双引号" "
包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出。这种方式比较适合字符串中附带有变量和命令并且想将其解析后再输出的变量定义。
我的建议:如果变量的内容是数字,那么可以不加引号;如果真的需要原样输出就加单引号;其他没有特别要求的字符串等最好都加上双引号,定义变量时加双引号是最常见的使用场景。
将命令的结果赋值给变量
Shell 也支持将命令的执行结果赋值给变量,常见的有以下两种方式:
variable=`command`
variable=$(command)
第一种方式把命令用反引号` `
(位于 Esc 键的下方)包围起来,反引号和单引号非常相似,容易产生混淆,所以不推荐使用这种方式;
第二种方式把命令用$()
包围起来,区分更加明显,所以推荐使用这种方式。
只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
#!/bin/bash myUrl="http://www.google.com" readonly myUrl //之后不能被更改,否则会报错
删除变量
unset variable_name
shell变量的作用域
Shell 变量的作用域可以分为三种
全局变量:当前shell中定义的变量(函数外部定义的变量),函数内部定义的变量(变量前不加local)都是全局变量,全局变量只在当前shell中有效,包括当前shell的函数内部,在子shell和父shell中无效
局部变量:在函数内部定义,并且前面加local的变量,此变量只在函数内部有效
函数内部定义的变量,没有local时为全局变量,有local时为局部变量
环境变量:在当前shell和子孙shell中都有效。使用export可以将以定义的变量变成环境变量。
个人理解:当父shell产生子shell时,子shell会将父shell的环境变量复制一份作为自己的环境变量。而全局变量和局部变量不会被复制。所以子shell看似是能够访问父shell的环境变量,其实是访问了自己的环境变量(也就是父shell环境变量的复制品),在子shell生成后,父shell的环境变量和子shell的环境变量是相互独立的,修改后不会相互影响
如果父shell打开的子shell通过&在后台运行,那么父shell执行结束或者父shell被kill,子shell仍然继续运行,而且环境变量不会失效(因为已经复制,是属于子shell自己的环境变量)
环境变量也是临时的
一个普通的全局变量通过export命令导出后就变成了环境变量。但export导出的环境变量是临时性的,只在当前shell和其子shell中有效。当重新打开一个新的shell时并不起作用。
要想让一个变量在所有 Shell 进程中都有效,不管它们之间是否存在父子关系,该怎么办呢?
只有将变量写入 Shell 配置文件中才能达到这个目的!Shell 进程每次启动时都会执行配置文件中的代码做一些初始化工作,如果将变量放在配置文件中,那么每次启动进程都会定义这个变量。