shell浅谈之一变量和引用

一、简介

       变量是脚本语言的核心,shell脚本又是无类型的。变量本质上存储数据的一个或多个计算机内存地址,分为本地变量(用户当前shell生命期使用,随shell进程的消亡而无效,类似局部变量)、环境变量(适用于所有由登录进程所产生的子进程)和位置参数(向shell脚本传递参数,只读)。而shell使用变量就需要引用,它们密切相关。

二、详解

1、变量赋值      

(1)变量赋值规则:等号两边不能有空格、value值包括空格必须用双引号、变量名只能包括字母数字和下画杠,并变量名不能以数字开头。

(2)如果value值中有空格,需要用双引号引以来。variable="hello world"。

(3)unset命令清除变量的值。

(4)变量赋值模式

(5)readonly将变量设置为只读,只读变量不能再次进行赋值操作。

2、无类型的变量

(1)C中定义变量需要声明整型、浮点型、字符型等,而shell脚本变量却是无类型的。shell不支持浮点型只支持整型和字符型,同时字符型还具有一个整型值0(判断标准:变量中只包含数字是数值型其他是字符串)。

#!/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}开始参数号需要用花括号括起来。

#!/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的版本信息。

#!/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脚本:

#!/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记录脚本从开始执行到结束所耗费的时间(单位为秒)。调试性能时比较有用。

#!/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放在脚本中可以规定脚本的执行时间。

#!/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命令)。

#!/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语言风格的变量操作。

#!/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的间接引用。

#!/bin/bash
variable1=variable2
variable2=Hadoop
echo "varialbe1=$variable1"

eval tempvar=\$$variable1
echo "tempvar=$tempvar"

echo "Indirect ref variable1 is :${!variable1}"

例:使用间接变量引用实现数据库表格的查找:

#!/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)双引号和单引号

       双引号引用除美圆符号($)、反引号(`)和反斜线(\)之外的所有字符,即$和`及\在双引号中仍被解释为特殊意义,利用双引号引用变量能防止字符串分割,而保留变量中的空格。因此双引号的引用方式称为部分引用。


        单引号中字符除单引号本身之外都解释为字面意义,不再具备引用变量的功能,单引号的引用方式称为全引用。

#!/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)反斜线符号(\)表示转义,将屏蔽下一个字符的特殊意义,而以字面意义解析它。


#!/bin/bash

variable="(]\\{}\$\""
echo $variable
echo "$variable"

IFS='\'
echo $variable
echo "$variable"
exit 0

(2)转义符除了屏蔽特殊字符的特殊意义外,加上一些字母能够表达特殊的含义。

#!/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默认是输出文本后自动换行。

三、总结

(1)从shell的基础开始了解,一步步向上走。

(2)可发邮件沟通,相互提高!邮箱地址[email protected]

你可能感兴趣的:(Shell基础)