# shell 变量 ## 1 变量字符串 在一个脚本周期内,其值可以发生改变的量就是变量。 ### 命名规则: 在定义变量时,有一些规则需要遵守: * 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。 * 等号左右两侧不能有空格,可以使用下划线“_”,变量的值如果有空格,需要使用单引号或双引号包括。如:“test=“hello world!””。 * 不能使用标点符号,不能使用bash里的关键字(可用help命令查看保留关键字)。 * 环境变量建议大写,便于区分 ### 变量分类 1. 用户自定义变量。由用户自定义的变量名和变量值。 2. 环境变量:保存和系统操作环境相关的数据。分为系统定义的环境变量和用户自定义的环境变量。 3. 位置参数变量:向脚本中传递参数或数据。变量名不能自定义,变量作用固定。 4. 预定义变量:Bash中已经定义好的变量。变量名自定义,变量作用也是固定的。 ## 2 用户变量 ### 变量定义
1
2
3
4
5
6
7
8
9
[root@localhost ~]$ 2name="shen chao"
-bash: 2name=shen chao: command not found
#变量名不能用数字开头
[root@localhost ~]$ name = "shenchao"
-bash: name: command not found
#等号左右两侧不能有空格
[root@localhost ~]$ name=shen chao
-bash: chao: command not found
#变量的值如果有空格,必须用引号包含
### 变量调用
1
2
3
4
5
[root@localhost ~]$ name="shen chao"
#定义变量name
[root@localhost ~]$ echo $name #调用变量使用 $变量名
shen chao
#输出变量name的值
### 变量查看
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@localhost ~]$ set [选项]
选项:
-u:如果设定此选项,调用未声明变量时会报错(默认无任何提示)
-x:如果设定此选项,在命令执行之前,会把命令先输出一次
+<参数> :取消某个set曾启动的参数。

[root@localhost ~]$ set
BASH=/bin/bash
…省略部分输出…
name='shen chao'
#直接使用set 命令,会查询系统中所有的变量,包含用户自定义变量和环境变量
[root@localhost ~]$ set -u
[root@localhost ~]$ echo $file
-bash: file: unbound variable
#当设置了-u选项后,如果调用没有设定的变量会有报错。默认是没有任何输出的。
[root@localhost ~]$ set -x
[root@localhost ~]$ ls
+ls --color=auto
anaconda-ks.cfginstall.loginstall.log.syslog sh tdir testtestfile
#如果设定了-x选项,会在每个命令执行之前,先把命令输出一次

[root@localhost ~]$ set +x
#取消启动的x参数
### 变量删除
1
[root@localhost ~]$ unset 变量名
## 3 环境变量 ### 环境变量设置
1
2
[root@localhost ~]$  export age="18"
#使用export声明的变量即是环境变量
### 环境变量查看
1
2
env
env命令只能查看环境变量,set命令可以产看所有变量。
### 环境变量删除
1
2
[root@localhost ~]$ unset gender   #删除环境变量gender
[root@localhost ~]$ env | grep gender
### 系统默认的环境变量
1
2
3
4
5
6
7
8
9
[root@localhost ~]$ env
HOSTNAME=localhost.localdomain #主机名
SHELL=/bin/bash #当前的shell
TERM=linux #终端环境
HISTSIZE=1000 #历史命令条数
SSH_CLIENT=192.168.4.1594824 22 #当前操作环境是用ssh连接的,这里记录客户端ip
SSH_TTY=/dev/pts/1 #ssh连接的终端时pts/1
USER=root #当前登录的用户
..........更多参数可以使用set和env命令查看.............
## 4 参数变量 * `$n`n为数字,$0表示当前Shell脚本程序的名称,1-9代表第一到第九个参数 , 十 以 上 的 参 数 需 要 用 大 括 号 包 含 , 如 9代表第一到第九个参数,十以上的参数需要用大括号包含,如9代表第一到第九个参数,十以上的参数需要用大括号包含,如`{10}` * `$*` 这个变量代表命令行中所有的参数,`$*`把所有的参数看成一个整体 * `$@` 这个变量也代表命令行中所有的参数,不过`$@`把每个参数区分对待 * `$#` 这个变量代表命令行中所有参数的个数 ### 位置参数`$n`,`$*`,`$@` `$1` 是你给你写的shell脚本传的第一个参数,`$2` 是你给你写的shell脚本传的第二个参数…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@localhost sh]$ vim test.sh
#!/bin/sh
echo "shell脚本本身的名字: $0"
echo "传给shell的第一个参数: $1"
echo "传给shell的第二个参数: $2"
[root@localhost sh]$ vi parameter2.sh
#!/bin/bash
for i in"$*"
#定义for循环,in后面有几个值,for会循环多少次,注意“$*”要用双引号括起来
#每次循环会把in后面的值赋予变量i
#Shell把$*中的所有参数看成是一个整体,所以这个for循环只会循环一次
do
echo "The parameters is: $i"
#打印变量$i的值
done
x=1
#定义变量x的值为1
for y in"$@"
#同样in后面的有几个值,for循环几次,每次都把值赋予变量y
#可是Shel1中把“$@”中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次
do
echo "The parameter$x is: $y"
#输出变量y的值
x=$(( $x +1 ))
#然变量x每次循环都加1,为了输出时看的更清楚
done
## 4 预定义变量 * `$?` 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非О(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。 * `$$` 当前进程的进程号(PID) * `$!` 后台运行的最后一个进程的进程号(PID) ### `$?`、`$$`、`$!`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@localhost sh]$ ls
count.sh hello.sh parameter2.sh parameter.sh
#ls命令正确执行
[root@localhost sh]$ echo $?
#预定义变量“$?”的值是0,证明上一个命令执行正确
[root@localhost sh]$ ls install.log
ls:无法访问install.log:没有那个文件或目录
#当前目录中没有install.log文件,所以ls命令报错了
[root@localhost sh]$ echo $?
2
#变量“$?”返回一个非О的值,证明上一个命令没有正确执行
#至于错误的返回值到底是多少,是在编写ls命令时定义好的,如果碰到文件不存在就返回数值2

[root@localhost sh]$ vi variable.sh
#!/bin/bash
echo "The current process is $$"
#输出当前进程的PID.
#这个PID就是variable.sh这个脚本执行时,生成的进程的PID
find /root -name hello.sh &
#使用find命令在root目录下查找hello.sh文件
#符号&的意思是把命令放入后台执行,工作管理我们在系统管理章节会详细介绍
echo "The last one Daemon process is $!"
#输出这个后台执行命令的进程的PID,也就是输出find命令的PID号
## 5 只读变量
1
2
3
4
5
6
7
[root@localhost sh]$ vi readonly.sh
#!/bin/bash
a=10
#语法:readonly 变量名
readonly a
a=20 #会报错readonly variable
echo $a
## 6 接收键盘输入
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost ~]$ read [选项][变量名]
选项:
-a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。
-p: “提示信息”:在等待read输入时,输出提示信息
-t: 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间
-n: 数字:read命令只接受指定的字符数,就会执行
-s: 隐藏输入的数据,适用于机密信息的输入
-d: 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志。
-e: 在输入的时候可以使用命令补全功能。
变量名:
变量名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY.
如果只提供了一个变量名,则整个输入行赋予该变量.
如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余的所有字
### 使用实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@localhost sh]$ vi read.sh
#!/bin/bash

read -t 30 -p "Please input your name: " name
#提示“请输入姓名”并等待30 秒,把用户的输入保存入变量name 中
echo "Name is $name"
#看看变量“$name”中是否保存了你的输入

read -s -t 30 -p "Please enter your age: " age
#提示“请输入年龄”并等待30秒,把用户的输入保存入变量age中
#年龄是隐私,所以我们用“-s”选项隐藏输入
echo -e "\n"
#调整输出格式,如果不输出换行,一会的年龄输出不会换行
echo "Age is $age"

read -n 1 -t 30 -p "Please select your gender[M/F]:" gender
#提示“请选择性别”并等待30秒,把用户的输入保存入变量gender
#使用“-n1”选项只接收一个输入字符就会执行(都不用输入回车)
echo -e "\n"
echo "Sex is $gender"
## 7 数组变量 bash支持一维数组(不支持多维数组),并且没有限定数组的大小。 类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。 ### 定义数组 在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
1
数组名=(值1 值2 ... 值n)
例如:
1
array_name=(value0 value1 value2 value3)
### 读取数组 读取数组元素值的一般格式是:
1
${array_name[index]}
### 获取数组中的所有元素 使用 @ 或 * 可以获取数组中的所有元素,例如:
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"
### 获取数组的长度 获取数组长度的方法与获取字符串长度的方法相同,例如:
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"