变量是任何程序或脚本的重要组成部分。变量为程序或脚本访问内存中的可被修改的一块数据提供了简单的方式。Linux Shell中的变量可以被指定为任意的数据类型。Shell中有两种变量的类型:系统变量(环境变量)和用户自定义的变量(本地变量或Shell变量)。

  环境变量:作用域为当前shell进程及其子进程;环境变量一般均为大写。常用的环境变量有:

系统变量含义
BASH_VERSION保存bash实例的版本
DISPLAY设置X display名字
EDITOR设置默认的文本编辑器
HISTFILE保存命令历史的文件名
HISTFILESIZE命令历史文件所能包含的最大行数
HISTSIZE
记录在命令历史中的命令数
HOME
当前用户的主目录
HOSTNAME计算机主机名
IFS
定义shell的内部字段分隔符
PATH
搜索命令的路径
PS1
提示符设定
PWD
当前工作目录
SHELL
登录shell路径
TERM
登陆终端类型
TMOUNT设置shell内建命令read默认超时时间,单位为秒。

  设置:export VARNAME=VALUE   (VARNAME=VALUE  ; export VARNAME)

  撤消:unset VARNAME

  查看当前shell中变量:set

  查看当前shell中的环境变量:printenv  env   export

[root@mylinux ~]# env
HOSTNAME=mylinux
TERM=linux
SHELL=/bin/bash
HISTSIZE=3000
SSH_CLIENT=211.103.109.22 10164 22
QTDIR=/usr/lib64/qt-3.3
QTINC=/usr/lib64/qt-3.3/include
SSH_TTY=/dev/pts/0
HISTFILESIZE=50
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=zh_CN.UTF-8
PYTHONSTARTUP=/root/.pythonstartup.py
SHLVL=1
HOME=/root
LOGNAME=root
QTLIB=/usr/lib64/qt-3.3/lib
CVS_RSH=ssh
SSH_CONNECTION=211.103.109.22 10164 10.104.160.241 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
PROMPT_COMMAND=history -a
HISTTIMEFORMAT=%F %T 
G_BROKEN_FILENAMES=1
_=/bin/env

本地变量:set VARNAME=VALUE:   作用域为当前bash进程,对子shell无效;

局部变量:local VARNAME=VALUE:作用域为当前代码段;

位置变量:

  $0 获取当前执行的shell脚本文件名,包括脚本路径

  $n 当前脚本的第n个参数,如果n大于9,要用大括号括起来${n}。

  $?: 上一个命令的执行状态返回值.  

  $#:命令行参数的个数

  $*: 参数列表  所有的参数,被当作一个字符串

  $@:参数列表  所有的参数,每个参数都是一个独立的字符串    

  Shift [n] :移去位置变量

  basename $0: 执行脚本的基名   

  dirname  $0:执行脚本的路径

  $PS1: 主提示符

  $PS2:第二提示符,补充完全命令输入时的提示符

  $PS3: 第三提示符,用于select命令中

  $PS4:第四提示符,当使用-x选项调用脚本时,显示的提示符,默认为+号

  $SECONDS: 当前脚本已经运行的时长

  $$:当前脚本进程PID

程序执行,可能有两类返回值:

  程序执行结果   

  程序状态返回代码(0-255)0: 正确执行  1-255:错误执行1,2,127系统预留。

内置变量:

  echo args-------将echo命令后面指定的字符串即变量等显示在标准输出

参数说明
-n不换行输出内容
-e解析转义字符
\n换行
\r回车
\t制表符
\b
退格
\v
纵向制表符

  eval args--------当shell程序执行到eval语句时,shell读入参数args,并将它们组合成一个新命令执行

  exec-------------能够在不创建新的子进程的前提下,转去执行指定的命令,当指定命令执行完毕,还进程终止  

  read-------------从标准输入读取字符串等信息,传给shell程序内部定义的变量  


BASH的引号引用

`  `或$(command): 命令替换,内层``使用要用\转义

"  ": 弱引用,可以实现变量替换;

'   ': 强引用,不完成变量替换

“引用”命令的执行结果,要使用命令引用;

[root@mylinux ~]# wc -l  /etc/passwd | cut -d: -f1
31 /etc/passwd
[root@mylinux ~]# RESAULTS=`wc -l  /etc/passwd | cut -d: -f1`
[root@mylinux ~]# echo $RESAULTS
31 /etc/passwd

命令的执行结果赋值给某变量,要使用命令引用.

  如USERID=`id -u user1`; (等号两边无空格)

命令的执行状态结果,要直接执行此命令,一定不能引用;

  如: if id user1一句中的id命令就一定不能加引号;

   

参数替换

  不含有“:”的,只要定义了就生效,不管是否为空;含有“:”的,即使定义了,但是为空就不生效,用来替换的内容可以是字符串、变量、命令的输出;被替换的内容是变量,如$a、$1

${par:-word}:若par不空则返回par的值,否则返回word.但不会赋值给par

${par:+word}:若par不空则返回word的值,否则返回空.

${par:=word}:若par不空则返回par的值,否则返回word,并赋值给par.

${par:?message}:若par为空或已被删除,那么将消息message送到标准错误输出;


字符串匹配处理

1)字符串长度:

${#var}表示$var的长度

${#n}表示脚本的第n个参数的长度

${#@}表示脚本的所有参数的个数,等效于$#

另外,数组中某个元素的长度 ${#array[n]}

2)字符串的前后截取,pattern一般是个命令行glob,匹配的即为被去掉的字符:

${var#pattern} 最短头匹配截取

${var##Pattern}最大头匹配截取

${var%Pattern} 最短尾匹配截取

${var%%Pattern}最大尾匹配截取

3)字符串位置,postion为第几个位置,此位置前面的字符为被匹配的(被删除的),length表示剩下的字符的长度:

${var:postion}#   从左往右,匹配postion之左的,留下之后的

${var:(-postion)} # 从右往左,匹配postion之左的,()是为了避免和${var-default}冲突

${var:postion:length} # 匹配postion位置之前的同时,显示之后的长度为length

4)字符串替换,分第一个替换和全局替换,前缀替换后缀替换,同样支持glob:

${var/Pattern/Replacement}   # 第一次匹配的被替换,类似:sed 's/Pattern/Replacement/'

${var//Pattern/Replacement}  # 全局的匹配被替换,类似:sed 's/Pattern/Replacement/g'

${var#/prefix/Replacement}   # 前缀替换

${var%/suffix/Replacement}   # 后缀替换

5)得到变量名,输出所有前缀一样的变量名,不支持glob(通配符)

${!var_prefix*} 或 ${!var_prefix@}


shell脚本变量输入

  Shell变量除了可以直接赋值或脚本传参外,还可以使用read命令从标准输入获得参数。

read [参数] [变量名]

常用参数:

-p:设置提示信息

-t:设置超时时间

[root@mylinux ~]# read -p "please input two number :" a1 a2
please input two number :15 69
[root@mylinux ~]# echo $a1 $a2
15 69


变量的数值计算

1、let算术运算表达式   

  let C=A+B (算术表达式中不能有空格)

[root@mylinux ~]# let a=5*8
[root@mylinux ~]# echo $a
40
[root@mylinux ~]# a=5
[root@mylinux ~]# b=6
[root@mylinux ~]# let c=a*b
[root@mylinux ~]# echo $c
30

2、let I+=1 相当于 let I++     

   let I-=1 相当于 let I--

[root@mylinux ~]# echo $c
30
[root@mylinux ~]# let c-=1
[root@mylinux ~]# echo $c 
29
[root@mylinux ~]# let c+=1
[root@mylinux ~]# echo $c 
30

3、$[算术运算表达式]    

  C=$[A+B]

[root@mylinux ~]# c=$[1+2]
[root@mylinux ~]# echo $c
3
[root@mylinux ~]# a=2
[root@mylinux ~]# b=3
[root@mylinux ~]# c=$[a+b]
[root@mylinux ~]# echo $c 
5

4、$((算术运算表达式))   

  C=$((A+B))  (只能进行整数运算)

[root@mylinux ~]# c=$((1+2))
[root@mylinux ~]# echo $c
3
[root@mylinux ~]# a=2
[root@mylinux ~]# b=3
[root@mylinux ~]# c=$((a+b))
[root@mylinux ~]# echo $c
5

5、expr 算术运算表达式 

  表达式中各操作数及运算符之间要有空格,乘号要转义

  计算结果要使用命令引用  C=`expr $A + $B`    (可用于判断是否为整数)

[root@mylinux ~]# expr 6 + 8
14
[root@mylinux ~]# a=4
[root@mylinux ~]# b=6
[root@mylinux ~]# expr $a + $b
10
[root@mylinux ~]# expr 6 * 8
expr: 语法错误
[root@mylinux ~]# expr 6 \* 8
48

   expr length STRING 计算字符STRING串长度

[root@mylinux ~]# expr length "1234225234234"
13

   expr 字符串: 表达式     字符串匹配(可用于判断文件扩展名)

[root@mylinux ~]# expr "abc" : ".*\.log" &>/dev/null       
[root@mylinux ~]# echo $?
1
[root@mylinux ~]# expr "abc.log" : ".*\.log" &>/dev/null 
[root@mylinux ~]# echo $?
0

6、bc  linux下的计算器(支持小数运算)

条件测试(整数,字符,文件,逻辑)


  通常,在bash的各种条件结构和流程控制结构中都要进行各种测试,然后根据测试结果执行不同的操作,有时也会与if条件语句相结合,来完成判断,以减少程序的运行错误。

条件测试常用的语法形式有:

格式一: test 测试表达式

格式二: [ 测试表达式 ]  (中括号两端有空格)

格式三: [[<测试表达式>]](内中括号两端有空格)

格式四: ((测试表达式))

整数比较操作:

在[]以及test中使用的比较符号在(())和[[]]中使用的比较符号说明
-eq==或=相等
-ne!=不相等
-gt
>大于
-ge
>=大于等于
-lt
<小于
-le
<=小于等于

说明:

 '='和'!='也可以在[]中做比较使用,但是在[]中使用包含'>'和'<'的符号时,需要用反斜线转义。

字符串测试:

  字符串测试操作符的作用包括:比较两个字符串是否相同、测试字符串的长度是否为零、字符串是否为NULL等。

常用字符串测试符说明
-n "字符串"若字符串的长度不为0,则为真,即测试表达式成立
-z "字符串"若字符串的长度为0,则为真,即测试表达式成立
"字符串1" = "字符串2"若字符串1等于字符串2,则为真,即测试表达式成立
"字符串1" != "字符串2"若字符串1不等于字符串2,则为真,即测试表达式成立
"字符串" =~ 模式左侧是字符串,右侧是一个模式,判定左侧的字符串能否被右侧的模式所匹配;通常只在[[]]中使用;模式中可以使用行首、行尾锚定符;但模式不要加引号;

说明:

 对于字符串的测试,一定要将字符串加双引号之后再进行比较

 比较符号(如=和!=)的两端一定要有空格

文件测试操作:

常用文件测试操作符说明
-d 文件文件存在且为目录则为真
-f 文件文件存在且为普通文件则为真
-e 文件文件存在则为真
-r 文件文件存在且可读则为真
-s 文件文件存在且文件大小不为0则为真
-w 文件文件存在且可写则为真
-x 文件文件存在且可执行则为真
-L 文件文件存在且为链接文件则为真
f1 -nt f2文件f1比文件f2新则为真,根据文件的修改时间来计算
f1 -ot f2文件f1比文件f2旧则为真,根据文件的修改时间来计算

逻辑测试:

在[]和test中使用的操作符在(())和[[]]中使用的操作符说明
-a&&
-o||
!!

说明:

 在连接两个含[]、test或[[]]的表达式时可用&&或||


管道和重定向

  几乎所有的命令都会产生到屏幕的输出和从键盘获取输入,而在Linux系统中可以将输出发送到指定的文件,或从文件中读取输入。在Linux中一切皆文件,所以硬件在Linux系统中同样的表示为文件:

默认输入设备:标准输入, STDIN, 0               

默认输出设备:标准输出,STDOUT, 1

标准错误输出:STDERR, 2  

输入重定向:

  <:输入重定向

  <<:此处创建文件,常用于在脚本中创建文件或生成菜单(如:cat <<EOF)                     

输出重定向:

  >: 覆盖标准输出

  >>:追加标准输出

错误重定向:

  2>: 重定向错误输出

  2>>: 追加方式

  &>: 重定向标准输出或错误输出至同一个文件

  >&fd:输出到定义的文件描述符    (如:  2>&1)

exec fd  <>file (打开file,关联到文件描述符fd,可读写)  

exec fd &- 关闭文件描述符  

set -C:禁止对已经存在文件使用覆盖重定向;强制覆盖输出,则使用 >|

set +C:关闭上述功能


管道:前一个命令的输出,作为后一个命令的输入

命令1 | 命令2 | 命令3 | ...

注:最后一个命令会在当前shell进程的子shell进程中执行

tee:将输入复制给每一个指定的文件和标准输出