第六章 shell学习之变量和引用
变量本地变量:类似于局部变量,只在当前shell进程有效
环境变量:适用于所有登录进程所产生的子进程
位置参数:用于向shell脚本传递参数,只读
变量替换和赋值
引用变量值就称为变量替换,$就为变量替换符号,如a为变量名则$a或${a}为变量值
将值赋给某个变量名就称为变量赋值,格式:variable=value或${ variable=value },如值中包含空格则必须用""
清除变量的值:
unset 变量名
设置只读变量:
variable=value
readonly variable
还可以用declare和typeset实现
查看系统中的所有只读变量:
# readonly
declare -ar BASH_VERSINFO='(="3" ="2" ="25" ="1" ="release" ="x86_64-redhat-linux-gnu")'
declare -ir EUID="0"
...
变量赋值的模式
1.variable:?value或variable?value
对未赋值的variable显示系统错误
# echo ${a:?blue}
bash: a: blue
# a=black
# echo ${a:?blue}
black
2.variable:=value
对未赋值的variable,将value值赋给它
# a=black
# echo ${a:=blue}
black
# unset a
# echo ${a:=blue}
blue
# echo $a
blue
3.variable:-value
对未赋值的variable,返回value,但是variable仍未赋值
# unset a
# echo ${a:-blue}
blue
# echo ${a:?blue}
bash: a: blue
无类型的shell脚本变量
shell脚本变量是无类型的,并且同时具有数字型和字符型两种赋值,可以不用预定义变量而直接使用,数字型的初始值为0,字符型的初始值为空
# cat a.sh
#! /bin/sh
c=""
echo "c=$c"
let "c+=1" #let命令用于执行算数运算,let "c+=1"等价于c+=1
echo "c=$c"
echo "e=$e"
let "e+=1"
echo "e=$e"
e="hello" #此时该变量的数字值又变为0
echo "e=$e"
let "e+=2"
echo "e=$e"
# ./a.sh
c=
c=1
e=
e=1
e=hello
e=2
环境变量
父进程的环境变量可以传递给子进程,但是子进程的环境变量(或者修改了父进程定义的环境变量)传递不了也影响不了父进程
定义环境变量:
ENVIRON-VARIABLE=value
export ENVIRON-VARIABLE
习惯环境变量用大写
export表明此变量为环境变量
清除环境变量:
unset ENVIRON-VARIABLE
重要的环境变量:
1.PWD和OLDPWD
PWD记录当前目录,OLDPWD记录旧的工作目录
# echo $PWD
/tmp
# cd
# echo $PWD
/root
# echo $OLDPWD
/tmp
2.PATH
shell为每个输入命令搜索PATH中的目录列表
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
# export PATH=$PATH:/tmp/bin #添加新路径
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/tmp/bin
3.HOME
用户家目录的路径
# echo $HOME
/root
4.SHELL
保存默认的shell值(/bin/bash)
5.USER和UID
已登录用户的名字和已登录用户的ID
# echo $USER $UID
root 0
6.PPID和$
$PPID当前进程的父进程号,$$为当前进程的进程号
7.PS1和PS2
分别为开头的提示符和分行的提示符(即命令分多行输入时的提示符)
# echo $PS1
[\u@\h \W]\$
# echo $PS2
>
\u代表当前用户名
\h代表主机名
\H代表主机名和域名
\W代表当前工作目录的名字
\w代表当前工作目录的完整路径
\$ UID为0则显示#,否则打印$
8.IFS
指定shell的输入域分隔符,默认为空格
# export IFS=" "
# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin:/tmp/bin
# export IFS=:
# echo $PATH
/usr/kerberos/sbin /usr/kerberos/bin /usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin /usr/X11R6/bin /root/bin /tmp/bin
环境变量配置文件
在用户的根目录中,为隐藏文件
1..bash_profile
用户登录时自动执行,初始化环境变量,如果不存在该文件则执行/etc/profile
可以自己加入新的环境变量,并且执行. .bash_profile或者source .bash_profile立即生效(注销也可以)
source命令等价于.命令
直接执行文件是启动一个子shell,而子shell脚本设置的环境变量无法影响当前shell脚本,soure命令(或.命令)让简本在当前shell执行
# cat .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
2..bashrc
设置子shell的环境变量,使得用户登录时的环境变量设置与子shell的环境变量设置相分离,提高灵活性
3. .bash_logout
在用户注销时执行,可以写入清楚某些环境变量的命令,也可以不存在
export PATH
unset USERNAME
父进程,子进程环境变量关系
子进程能继承父进程的环境变量,但是子进程修改父进程的环境变量只对子进程有效,不影响父进程环境变量,子进程创建的环境变量父进程也接收不到,而本地变量则互不影响
例:
# cat father.sh
#! /bin/bash
fatherLocal="fatherLocal"
fatherEnviron="fatherEnviron"
export fatherEnviron
echo "in fahter.sh"
echo "father process> echo "fatherLocal is $fatherLocal"
echo "fatherEnviron is $fatherEnviron"
$PWD/child.sh
echo "return to father.sh"
echo "fatherLocal is $fatherLocal"
echo "fatherEnviron is $fatherEnviron"
# cat child.sh
#! /bin/bash
echo "in child.sh"
echo "child process> echo "fatherLocal is $fatherLocal"
echo "fatherEnviron is $fatherEnviron"
echo "change faterEnviron"
export "fatherEnviron=redefinfatherEnviron"
echo "new fatherEnviron is $fatherEnviron"
结果:
# ./father.sh
in fahter.sh
father process> fatherLocal is fatherLocal
fatherEnviron is fatherEnviron
in child.sh
child process> fatherLocal is
fatherEnviron is fatherEnviron
change faterEnviron
new fatherEnviron is redefinfatherEnviron
return to father.sh
fatherLocal is fatherLocal
fatherEnviron is fatherEnviron
位置参数
$0 脚本名称
$1 第一个参数
${10} 第十个参数,从10开始要加{}
$# 参数个数
$*或$@ 所有参数,不包括$0
$$ 进程号
$PPID 父进程号
$? 退出状态,0表示没有错误,非0表示有错误
引用
引用是屏蔽特殊字符的特殊意义,而将其解释为字面意义
"" 引用除了美元符号($),反引号(``),反斜杠(\)之外的所有字符
'' 引用除了''本身的所有字符
`` 反引号,shell将反引号中的内容解释为系统命令
\ 反斜杠,屏蔽下一个字符的特殊含义
对于变量加双引号可以保留多个空格(还有换行),而不解释为字段的分隔符(IFS默认为空),即双引号有防止变量变分隔符的作用
例:
# a="a b c"
# echo $a
a b c
# echo "$a"
a b c
# echo '$a'
$a
# echo 'why can't I'm you are'
why cant Im you are
# echo "why can't I'm you are"
why can't I'm you are
命令替换
将命令执行的标准输出替换该命令所在的位置
反引号(``)和$()
$()命令可以嵌套
$()将\就是\,而反引号(``)将\解释为空格
利用反引号可以将其它语言执行的结果赋值给shell变量,从而用shell处理
例:
# echo \\
\
# echo $(echo \\)
\
# echo `echo \\`
#空白行
command `echo` #command代表任何命令,这里相当于不带参数
command "`echo`"#带空字符串参数
command `echo x y`#带两个参数,为x和y
command "`echo x y`" #带一个参数,为x y
转义
作用:
1.解除一些特殊字符的含义
2.单个\在命令行中为出现二级提示符,在shell脚本中同样适用
3.在echo、sed、awk等命令中让一些字母能够表达特殊含义
1.
variable="()\\{}\$\""
echo $variable
echo "$variable"
IFS='\' #改变输入变量分隔符
echo $variable
echo "$variable" #双引号有防止变量变分隔符的作用,保留变量分隔符
# ./a3.sh
()\{}$"
()\{}$"
() {}$"
()\{}$"
2.
2.1
# echo \
> hello world
hello world
2.2
# echo \ #echo可以用""也可以不用
> "hello world"
hello world
2.3
# echo "\" #注意这和前面两个存在本质的区别,这里的\转义了"导致缺少后",补全命令才结束,和2.4同
> hello world"
"
hello world
2.4
# echo "
> hello
> world"
hello
world
2.5
# variable=\
> hello world
bash: world: command not found #变量赋值如果有空格必须用引号
2.6
# variable=\
> "hello world"
# echo $variable
hello world
2.7
# cat a5.sh
#! /bin/bash
echo \ #单个/在shell脚本中同样适用
hello world
# ./a5.sh
hello world
3.
\后跟字母的特殊含义:
\n 新的一行
\r 返回
\t tab键
\v或\f 换行但光标忍停留在原来的位置(横坐标相同)
\b 退格键
\a 发出警报声
\0xx ASCII码0xx对应的字符
例:
# echo hello\b\101
hellob101
# echo $'hello\b\101' #和-e ""基本等价
hellA
# echo -e "hello\b\0101" #注意\0101的0,没有0不能解析成ASCII码
hellA
# echo -e "hello\b\101"
hell\101
# echo -e hello\b\101 #注意-e没有""同样不能解析
hellob101
注意:
echo [选项] [字符串]
选项-e表示将转移符(\)后跟字符形成的特殊字符解释成特殊意义
选项-n表示输出文字后不换行:
# echo -n "hello"
hello#
页:
[1]