# Shell中的变量
[TOC]
## Shell定义变量需要遵循的规则
Shell编程中,使用变量无需事先声明,同时变量名的命名须遵循如下规则:
1. 首个字符必须为字母(a-z,A-Z),推荐统一使用大写字母
2. 中间不能有空格,可以使用下划线(_)
3. 不能使用标点符号
4. 不能使用bash里的关键字(可用help命令查看保留关键字)
## shell变量赋值
需要给变量赋值时,可以这么写:
`变量名=值`
## unset取消本地的环境变量
`unset USER`
## 变量种类
### Shll中系统环境变量
shell在初始化的时候会在执行`/etc/profile`和`~/.bash_profile`等初始化脚本,脚本中定义了一些环境变量,这些变量会在创建子进程时传递给子进程。
用`env`命令可以查看当前的环境变量。常用的系统环境变量如下:
>
`_`(下划线) 上一条命令的最后一个参数
`BASH` 展开为调用bash实例时使用的全路径名
`CDPATH` cd命令的搜索路径。它是以冒号分隔的目录列表,shell通过它来搜索cd命令指定的目标目录。例如.:~:/usr
`EDITOR` 内置编辑器emacs、gmacs或vi的路径名
`ENV` 每一个新的bash shell(包括脚本)启动时执行的环境文件。通常赋予这个变量的文件名是.bashrc。
`EUID` 展开为在shell启动时被初始化的当前用户的有效ID
`GROUPS` 当前用户所属的组
`HISTFILE` 指定保存命令行历史的文件。默认值是~/.bash_history。如果被复位,交互式shell退出时将不保存命令行历史
`HISTSIZE` 记录在命令行历史文件中的命令数。默认是500
`HOME` 主目录。未指定目录时,cd命令将转向该目录
`IFS` 内部字段分隔符,一般是空格符、制表符和换行符,用于由命令替换,循环结构中的表和读取的输入产生的词的字段划分
`LANG` 用来为没有以LC_开头的变量明确选取的种类确定locale类
`OLDPWD` 前一个工作目录
`PATH` 命令搜索路径。一个由冒号分隔的目录列表,shell用它来搜索命令,一个普通值为 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
`PPID` 父进程的进程ID
`PS1` 主提示符串,默认值是$
`PS2` 次提示符串,默认值是>
`PS3` 与select命令一起使用的选择提示符串,默认值是#?
`PS4` 当开启追踪时使用的调试提示符串,默认值是+。追踪可以用set –x开启
`PWD` 当前工作目录。由cd设置
`RANDOM` 每次引用该变量,就产生一个随机整数。随机数序列可以通过给RANDOM赋值来初始化。如果RANDOM被复位,即使随后再设置,它也将失去特定的属性
`REPLY` 当没有给read提供参数时设置
`SHELL` 当调用shell时,它扫描环境变量以寻找该名字。shell给PATH、PS1、PS2、MAILCHECK和IFS设置默认值。HOME和MAIL由login(1)设置
`SHELLOPTS` 包含一列开启的shell选项,比如braceexpand、hashall、monitor等
`UID` 展开为当前用户的用户ID,在shell启动时初始化
### Shell中局部变量
局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
#### 普通字符串的定义
>
变量名=value
变量名='value'
变量名="value"
**例一:**
~~~
a=192.168.0.200
b='192.168.0.200'
c="192.168.0.200"
echo "a=$a"
echo "b=$b"
echo "c=${c}"
~~~
**例一运行结果:**
~~~
a=192.168.0.200
b=192.168.0.200
c=192.168.0.200
~~~
**例二:**
~~~
a=192.168.0.200
a=192.168.0.200-$a
b='192.168.0.200-$a'
c="192.168.0.200-$a"
echo "a=$a"
echo "b=$b"
echo "c=$c"
~~~
**例二运行结果:**
~~~
a=192.168.0.200-192.168.0.200
b=192.168.0.200-$a
c=192.168.0.200-192.168.0.200-192.168.0.200
~~~
> **提示:**
定义变量a的方式是直接定义变量内容,内容一般为简单连续(无空格)的数字、字符串、路径名等;
定义变量b的方式是**通过单引号定义变量**,特点是输出变量时引号里是什么就输出什么,即使**内容中有变量也会把变量名原样输出**,适合定义显示纯字符串;
定义变量c的方式是通过**双引号定义变量**,特点是**输出变量时引号内的变量会经过解析后输出该变量内容**,而不是把引号中变量名原样输出,适合于字符串中附带变量的内容的定义。
#### 脚本中局部变量定义
存在于脚本函数(function)中的变量称为局部变量,要以local方式进行生命,使之只在本函数作用域内有效,防止变量在函数中的命名与变量外部程序中变量重名造成程序异常。
具体实例可以参考`/ect/init.d/functions`相关的定义方式。
### Shell中特殊变量
#### 位置变量
>
**$0:当前脚本的文件名**
**$n:n为从1开始的数字,$1是第一个参数,$2是第二个参数,${10}是第十个参数**
**$#:传入脚本的参数的个数**
$*:所有的位置参数(作为单个字符串)
$@:所有的位置参数(每个都作为独立的字符串)。
#### 进程状态变量
>
**$?:当前shell进程中,上一个命令的返回值,如果上一个命令成功执行则$?的值为0,否则为其他非零值,常用做if语句条件**
$$:当前shell进程的pid
$!:后台运行的最后一个进程的pid
$-:显示shell使用的当前选项
$_:之前命令的最后一个参数
### bash内部变量
有些内部命令在目录列表时是看不见的,他们有Shell本身提供,常见的内部命令:**echo**,**export**,**read**,**shift**,eval,exec,readonly,wait,exit和点(.)
#### **echo 变量名表**
将变量名表指定的变量显示到标准输出
#### **export 变量名=value**
Shell 可以用export把它的变量向下打入子Shell,从而让子进程继承父进程中的环境变量,但子Shell不能用export把他的变量向上带入父Shell
#### **read 变量名表**
从标准输入读取字符串,传给指定变量,可以在函数中用local变量名的方式申明局部变量。
#### **shift 语句**
shift 语句按如下方式重新命名所有的位置参数变量,即 $2成为$1,$3成为$2…在程序中每使用一次shift语句,都使得所有的位置一次向左移动一个位置,并使位置参数$#减1,直到减到0为止。
#### eval args
读入参数args ,并将他们组合成一个新的命令,然后执行
#### exec 命令参数
当Shell执行到exec语句时,不会去创建新的子进程,而是转去执行新的命令,当指定的命令执行完时,该进程(也就是当初的Shell)就终止了,所以shell程序中的exec后面的语句将不再被执行
#### readonly 变量名
从边准输入读字符床,传给指定变量