一、简介
变量是脚本语言的核心,shell脚本又是无类型的。变量本质上存储数据的一个或多个计算机内存地址,分为本地变量(用户当前shell生命期使用,随shell进程的消亡而无效,类似局部变量)、环境变量(适用于所有由登录进程所产生的子进程)和位置参数(向shell脚本传递参数,只读)。而shell使用变量就需要引用,它们密切相关。
二、详解
1、变量赋值
(1)变量赋值规则:等号两边不能有空格、value值包括空格必须用双引号、变量名只能包括字母数字和下画杠,并变量名不能以数字开头。
(2)如果value值中有空格,需要用双引号引以来。variable="hello world"。
(3)unset命令清除变量的值。
(4)变量赋值模式
(5)readonly将变量设置为只读,只读变量不能再次进行赋值操作。
2、无类型的变量
(1)C中定义变量需要声明整型、浮点型、字符型等,而shell脚本变量却是无类型的。shell不支持浮点型只支持整型和字符型,同时字符型还具有一个整型值0(判断标准:变量中只包含数字是数值型其他是字符串)。
[cpp]
view plain copy#!/bin/bash
a=2009
let "a+=1"
echo "a=$a"
b=xx09
echo "b=$b"
declare -i b
echo "b=$b"
let "b+=1"
echo "b=$b"
exit 0
(2)位置参数从命令行向shell脚本传递参数,$0表示脚本的名字,$1代表第一个参数,以此类推。从${10}开始参数号需要用花括号括起来。
[cpp]
view plain copy#!/bin/sh
echo "The script name is: $0" #$0表示脚本本身
echo "Parameter #1:$1"
echo "Parameter #2:$2"
echo "Parameter #3:$3"
echo "Parameter #4:$4"
echo "Parameter #5:$5"
echo "Parameter #6:$6"
echo "Parameter #7:$7"
echo "Parameter #8:$8"
echo "Parameter #9:$9"
echo "Parameter #10:${10}" #用大括号括起来
echo "-------------------------"
echo "All the command line parameters are: $*"
特殊的位置参数:
3、内部变量
内部变量指能够对bash shell脚本行为产生影响的变量,属于环境变量的范畴。
(1)BASH
BASH记录了shell的路径,通常是/bin/bash。内部变量SHELL是通过BASH的值确定当前Shell的类型,linux使用的是bash shell,因而两个变量的值都是/bin/bash。
(2)BASH_VERSINFO
它是一个包含6个元素的数组,这些元素用于表示bash的版本信息。
[cpp]
view plain copy#!/bin/bash
for n in 0 1 2 3 4 5
do
echo "BASH_VERSINFO[$n]=${BASH_VERSINFO[$n]}"
done
BASH_VERSINFO[0]表示bash shell的主版本号,BASH_VERSINFO[1]表示shell的次版本号,BASH_VERSINFO[2]表示shell的补丁级别,BASH_VERSINFO[3]表示shell的编译版本,BASH_VERSINFO[4]表示shell的发行状态,BASH_VERSINFO[5]表示shell的硬件架构。
(3)BASH_VERSION
linux系统的bash shell版本包含主次版本、补丁级别、编译版本和发行状态,即BASH_VERSINFO数组取值为0~4。显示BASH_VERSION的值。
(4)DIRSTACK
它显示目录栈的栈顶值。linux目录栈用于存放工作目录,便于程序员手动控制目录的切换,bash shell定义了两个系统命令pushd(将某目录压入目录栈并将当前工作目录切换到入栈的目录)和popd(将栈顶目录弹出并将当前工作目录切换到栈顶目录)来维护目录栈。
DIRSTACK记录栈顶目录值,初值为空。linux还有一个命令dirs用于显示目录栈的所有内容。
(5)GLOBIGNORE
它是由冒号分隔的模式列表,表示通配时忽略的文件名集合。一旦GLOBIGNORE非空,shell会将通配得到的结果中符合GLOBIGNORE模式中的目录去掉。例如ls a*列出当前目录以a开头的文件,设置GLOBIGNORE=“ar*”,再次执行ls a*将剔除以ar开头的文件。
(6)GROUPS
GROUPS记录了当前用户所属的群组,linux的一个用户可同时包含在多个组内,GROUPS是一个数组记录了当前用户所属的所有群组号。管理用户组的文件是/etc/group,格式:群组名:加密后的组口令:群组号:组成员,组成员(组成员列表)。
(7)HOSTNAME
HOSTNAME记录了主机名,linux主机名是网络配置时必须要设置的参数,可在/etc/sysconfig/network文件中设置主机名。/etc/hosts文件用于设定IP地址和主机名之间的对应关系,可快速从主机名查找IP地址。
(8)HOSTTYPE和MACHTYPE
都用于记录系统的硬件架构,它们与BASH_VERSINFO[5]等值
(9)OSTYPE
记录操作系统类型,linux系统中,$OSTYPE=linux。
(10)REPLY
REPLY变量与read和select命令有关。read用于读取标准输入(stdin)的变量值,read variable将标准输入存储到variable变量中,而read将读到的标准输入存储到REPLY变量中。
select脚本:
[cpp]
view plain copy#!/bin/bash
echo "Pls. choose your profession?"
select var in "Worker" "Doctor" "Teacher" "Student" "Other"
do
echo "The \$REPLY is $REPLY."
echo "Your preofession is $var."
break
done
”#?"提示符由shell提示符变量PS3进行设置(#?是其默认值)。修改export PS3="your choice:"。REPLY变量值为用户选择的序号,var变量为REPLY序号所对应的字符串。(11)SECONDS
SECONDS记录脚本从开始执行到结束所耗费的时间(单位为秒)。调试性能时比较有用。
[cpp]
view plain copy#!/bin/bash
count=1
MAX=5
while [ "$count" -le "$MAX" ];do
echo "This is the $count time to sleep."
let count=$count+1
sleep 1
done
echo "The running time of this script is $SECONDS"
(12)SHELLOPTS它记录了处于开状态的shell选项列表,它是一个只读变量。Shell选项用于改变Shell的行为,Shell选项有开和关两种状态,set命令用于打开或关闭选项。set -o optionname(打开名为optionname选项),set +o optionname(关闭名为optionname选项)。比如打开interactive(交互模式运行)可以使用set -o interactive或set -i等价。Shell选项有很多。
(13)SHLVL
记录Shell嵌套的层次,启动第一个shell时,$SHLVL=1,若在这个Shell中执行脚本,脚本中的SHLVL为2,脚本中再执行子脚本,SHLVL就会递增。
(14)TMOUT
用于设置Shell的过期时间,TMOUT不为0时,shell会在TMOUT秒后将自动注销,TMOUT放在脚本中可以规定脚本的执行时间。
[cpp]
view plain copy#!/bin/bash
TMOUT=3
echo "What is your name?"
read fname
if [ -z "$fname" ]; then
fname="(no answer)"
fi
echo "Your name is $fname"
用户有输入,脚本执行read后的程序,用户没有输入等待TMOUT秒后执行read后程序但fname会为空。4、有类型变量
Shell变量一般是无类型的,bash shell提供了declare和typeset两个命令用于指定变量的类型(它们完全等价)。declare [选项] 变量名,有6个选项。
declare命令-r选项将变量设置成只读属性,与readonly命令一样,变量值不允许修改。
declare命令-x选项将变量声明为环境变量,相当于export,但declare -x允许声明环境变量同时给变量赋值,而export不支持。
declare -i将变量定义为整型数,不能再按字符串形式处理改变量(和let命令进行算术运算一样,expr命令可以替换let命令)。
[cpp]
view plain copy#!/bin/bash
variable1=2009
variable2=$variable1+1
echo "variable2=$variable2"
let variable3=$variable1+1
echo "variable3=$variable3"
declare -i variable4
variable4=$variable1+1
echo "variable4=$variable4"
再介绍一种变量执行算术运算的方法:双圆括号即((...))格式。result=$((var1*var2));var1和var2执行乘法运算。双圆括号也可以使shell实现C语言风格的变量操作。[cpp]
view plain copy#!/bin/bash
((a = 2014))
echo "The initial value of a is:$a"
((a++))
echo "After a++,the value of a is:$a"
((++a))
echo "After ++a,the value of a is:$a"
((a--))
echo "After a--,the value of a is:$a"
((--a))
echo "After --a,the value of a is:$a"
双圆括号实现五种C语言风格的运算,自增自减是shell算术运算符中未曾定义过的,是C语言中的相关内容。a = 2014,C语言允许赋值两端有空格但shell不允许。双圆括号还可以实现更加复杂的C语言的运算如逻辑判断、三元操作等。
5、间接变量引用
该引用不是将变量引起来,而是理解为:如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用。bash shell提供了两种格式实现间接变量引用:eval tempvar=\$$variable和tempvar=${!variable},其中eval是关键字,用\$$形式得到variable的简介引用,用${!...}得到variable的间接引用。
[cpp]
view plain copy#!/bin/bash
variable1=variable2
variable2=Hadoop
echo "varialbe1=$variable1"
eval tempvar=\$$variable1
echo "tempvar=$tempvar"
echo "Indirect ref variable1 is :${!variable1}"
例:使用间接变量引用实现数据库表格的查找:[cpp]
view plain copy#!/bin/bash
S01_name="Li Hao"
S01_dept=Computer
S01_phone=025-83481010
S01_rank=5
S02_name="Zhang Ju"
S02_dept=English
S02_phone=025-83466524
S02_rank=8
S03_name="Zhu Lin"
S03_dept=Physics
S03_phone=025-83680010
S03_rank=3
PS3='Pls. select the number of student:'
select stunum in "S01" "S02" "S03"
do
name=${stunum}_name
dept=${stunum}_dept
phone=${stunum}_phone
rank=${stunum}_rank
echo "BASIC INFORMATION OF NO.$stunum STUDENT:"
echo "NAME:${!name}"
echo "DEPARTMENT:${!dept}"
echo "PHONE:${!phone}"
echo "RANK:${!rank}"
break
done
在间接变量引用中,第一个变量中存放的是最终值的地址,因此,间接变量引用使得shell编程实现了类似于C语言中指针的功能,在很多场合能够精简shell脚本。
6、引用
(1)引用指将字符串用引用符号引起来,以防止特殊字符被shell脚本重解释为其他意义。shell中定义了四种引用符号。
(2)双引号和单引号
双引号引用除美圆符号($)、反引号(`)和反斜线(\)之外的所有字符,即$和`及\在双引号中仍被解释为特殊意义,利用双引号引用变量能防止字符串分割,而保留变量中的空格。因此双引号的引用方式称为部分引用。
单引号中字符除单引号本身之外都解释为字面意义,不再具备引用变量的功能,单引号的引用方式称为全引用。
[cpp]
view plain copy#!/bin/bash
echo "Why can't I write 's between single quotes"
echo 'Why can'"'"'t I write' "'"'s between single quotes'
(3)反引号反引号进行命令替换(将命令的标准输出作为值赋给某个变量),等价于$(),同时$()形式的命令替换是可以嵌套的。如`pwd`和$(pwd)等价都为当前工作目录。
反引号与$()在处理双反斜线时存在区别,反引号将反斜线符号处理为空格,而$()符号将其处理为单斜线符。
7、转义
(1)反斜线符号(\)表示转义,将屏蔽下一个字符的特殊意义,而以字面意义解析它。
[cpp]
view plain copy#!/bin/bash
variable="(]\\{}\$\""
echo $variable
echo "$variable"
IFS='\'
echo $variable
echo "$variable"
exit 0
(2)转义符除了屏蔽特殊字符的特殊意义外,加上一些字母能够表达特殊的含义。
[cpp]
view plain copy#!/bin/bash
#echo不加e选项,按照字面含义解释\t等特殊符号
echo "\t\n\a\v"
#echo加上e选项后,按照特殊含义解释这些特殊符号
echo -e "\t\t\t\thello"
echo $'\t\thello'
echo -e "hello\v\v\v\vhello"
echo -e "\a\a\a\a"
echo -e "\042"
$''与-e选项等价。
(3)echo加-n选项表示输出文字后不换行,不带-n默认是输出文本后自动换行。