学习linux杂七杂八——关于shell中的变量
var=value 变量定义并赋值,注意等号前后不能与空格相邻,如果需要有空格(其他特> 殊字符,如$,回车,",',\等)可用转义字符\进行转义。
变量命名规则同C语言。
变量值两端可以用"或者',"号中的$保持变量特性不变,但'号中的特殊字符即为其字> 面值。
echo $var 获取变量的值。
neeo@neeo-labtop:~$ hi=hello #定义变量hi neeo@neeo-labtop:~$ echo $hi #获取变量hi的值 hello neeo@neeo-labtop:~$ hi=$hiworld #像这样不能实现将hi变量值变为helloworld的目的,因为$hiworld被认为是一个变量,而这个变量并不存在,hi变成了空值。 neeo@neeo-labtop:~$ echo $hi neeo@neeo-labtop:~$ hi=hello neeo@neeo-labtop:~$ hi=$hi,world #但是这样是可以工作的,原因是逗号不是合法变量名的一部分,只有$hi被识别为一个变量。 neeo@neeo-labtop:~$ echo $hi hello,world neeo@neeo-labtop:~$ hi=hello neeo@neeo-labtop:~$ hi="$hi"world #可以这样扩充变量值,注意双引号中的$符号依然具有其特殊性。 neeo@neeo-labtop:~$ echo $hi helloworld neeo@neeo-labtop:~$ hi=${hi}world #也可以这样,注意{}的位置和双引号的位置是不同的。 neeo@neeo-labtop:~$ echo $hi helloworldworld neeo@neeo-labtop:~$ hi='$hi'world #如果你写成了这样(双引号被单引号替代),$符号失去了其特殊性,变成了一个字面值,结果就是下面这样。 neeo@neeo-labtop:~$ echo $hi $hiworld
有关数组的定义 arr[index]=value
neeo@neeo-labtop:~$ arr[1]=one #这4行定义了一个数组 neeo@neeo-labtop:~$ arr[0]=zero neeo@neeo-labtop:~$ arr[2]=two neeo@neeo-labtop:~$ arr[10]=ten neeo@neeo-labtop:~$ echo $arr # $arr的结果等同于 arr[0], zero neeo@neeo-labtop:~$ echo ${arr} #结果同上 zero neeo@neeo-labtop:~$ echo "${arr},${arr[1]}" #看来像${arr[1]}这样可以取得arr[1]的值 zero,one neeo@neeo-labtop:~$ echo $arr[3] #那么这样能取得arr[3]的值么?看结果,不解释 zero[3] neeo@neeo-labtop:~$ echo ${arr[3]} #这样应该可以取到了吧!因为arr[3]没有值,当然为空。 neeo@neeo-labtop:~$ unset arr #(这里是剧透,unset下面才讲到)有意思的在这里,unset arr并不等同于unset arr[0],事实上,unset把整个arr都干掉了。注意区分上面的 echo $arr。
neeo@neeo-labtop:~$ echo ${arr[1]} #被unset扫荡过的arr,1号成员消失了。 neeo@neeo-labtop:~$
#不要走开哦,下面介绍declare时有数组定义的新方法。
neeo@neeo-labtop:~$ arr=(0 1 2) #还可以这样声明数组,注意值之间用空格分隔。 neeo@neeo-labtop:~$ echo ${arr} 0 neeo@neeo-labtop:~$ echo ${arr[2]} 2 neeo@neeo-labtop:~$
declare 和typeset
declare的执行方式:declare [-aAfFilrtux] [-p] [name[=value] ...]
其中:
-f #列出函数列表,包括函数体 -F #列出函数列表,尽显示名称 #------------分隔线,下面是设定变量属性用的---------- -a #变量为一个数组(就是类似C语言中的数组,用整数做下标) -A #变量为一个关联数组(用一个字符串做下标,key-value,类似于C#中的字典,健唯一) -i #变量为一个整数 -l #变量的值为小写(这是小写的L不适大写的i) -u #变量的值为大写 -r #变量为一个只读变量(很彪悍,不能改不能删,见下面讲到的readony) -x #声明为环境变量(类似于export,看下面) -t #变量具有'trace'属性
neeo@neeo-labtop:~$ declare -f | less #显示函数列表,包括函数体 #--------------下面是结果--------------------- _ImageMagick () { local prev; prev=${COMP_WORDS[COMP_CWORD-1]}; case "$prev" in -channel) COMPREPLY=($( compgen -W 'Red Green Blue Opacity \ Matte Cyan Magenta Yellow Black' -- "$cur" )); return 0 ;; -colormap) COMPREPLY=($( compgen -W 'shared private' -- "$cur" )); return 0 ;; #---------------此处省略无数字----------------- neeo@neeo-labtop:~$ declare -F | less #显示函数列表,仅名称 #--------------下面是结果--------------------- declare -f _ImageMagick declare -f __get_cword3 declare -f __get_cword4 declare -f __git_aliased_command declare -f __git_aliases declare -f __git_complete_file declare -f __git_complete_remote_or_refspec declare -f __git_complete_revlist declare -f __git_complete_strategy declare -f __git_compute_all_commands declare -f __git_compute_merge_strategies declare -f __git_compute_porcelain_commands declare -f __git_config_get_set_variables declare -f __git_find_on_cmdline declare -f __git_has_doubledash #---------------此处省略无数字----------------- neeo@neeo-labtop:~$ declare -a arr=(0 1 2 3) #定义数组 neeo@neeo-labtop:~$ echo ${arr[*]} #显示数组值,用*表示将数组所有内容取出组成一个字符串。 0 1 2 3 neeo@neeo-labtop:~$ echo ${arr[@]} #显示数组值,用 @表示将数组所有内容用空格分隔显示 0 1 2 3 neeo@neeo-labtop:~$ declare -A dict #定义一个关联数组 neeo@neeo-labtop:~$ dict[key]=value #设定一个键值 neeo@neeo-labtop:~$ echo ${dict[*]} #显示 value neeo@neeo-labtop:~$ echo ${dict[@]} #显示 value neeo@neeo-labtop:~$ echo ${dict[key]} #还是显示
value neeo@neeo-labtop:~$ declare -r var='readonly' #定义一个只读变量 neeo@neeo-labtop:~$ var='change' #这货不能更改了 bash: var: 只读变量 neeo@neeo-labtop:~$ unset var #你也别想unset他 bash: unset: var:无法重置:只读的 variable neeo@neeo-labtop:~$
对于已经定义好的变量,可以用readonly命令转变为只读
neeo@neeo-labtop:~$ declare normal=normal neeo@neeo-labtop:~$ readonly normal neeo@neeo-labtop:~$ unset normal bash: unset: normal:无法重置:只读的 variable neeo@neeo-labtop:~$ normal=change bash: normal: 只读变量 neeo@neeo-labtop:~$
typeset的用法和declare类似
unset var删除变量
neeo@neeo-labtop:~$ unset hi #删除变量hi,注意hi前面并没有$符号 neeo@neeo-labtop:~$ echo $hi #查看hi的值,变为空了。 neeo@neeo-labtop:~$
export var将变量设置为环境变量,像上面那样定义的变量并不是环境变量,姑且叫私有变量。二者的区别是环境变量是可以被子程序访问的,看下面的例子:
neeo@neeo-labtop:~$ hi=hello #定义变量hi neeo@neeo-labtop:~$ echo $hi #查看变量值 hello neeo@neeo-labtop:~$ bash #开启子shell neeo@neeo-labtop:~$ echo $hi #查看变量hi的值,为空,因为hi仅仅是父shell的私有变量,子shell不能访问。 neeo@neeo-labtop:~$ exit #退出子shell exit neeo@neeo-labtop:~$ export hi #用export命令将hi变量转变为环境变量 neeo@neeo-labtop:~$ bash #启动另一个子程序 neeo@neeo-labtop:~$ echo $hi #这回可以获取hi的值了。 hello neeo@neeo-labtop:~$ child='in child' #在子shell中定义变量child neeo@neeo-labtop:~$ echo $child #查看child的值 in child neeo@neeo-labtop:~$ export child #将child转变为环境变量。 neeo@neeo-labtop:~$ exit #退出子shell,回到父shell exit neeo@neeo-labtop:~$ echo $child #查看child的值,为空,因为在子shell中设定的环境变量,同样不能被父shell访问。 neeo@neeo-labtop:~$
那么,请问我在当前shell中设定的环境变量,在另一个shell中(新开的终端哦)能访问么?当然不能!
env 列出当前shell中的所有环境变量
neeo@neeo-labtop:~$ env | less #用less查看env的结果,不然实在是太多了 = =||| : #------------下面是结果----------------- ORBIT_SOCKETDIR=/tmp/orbit-neeo SSH_AGENT_PID=1944 TERM=xterm SHELL=/bin/bash XDG_SESSION_COOKIE=d764e95dfe46a11008ed453a50ab62c3-1354339100.454898-280573025 GOBIN=/home/neeo/go/bin/ WINDOWID=58721450 GNOME_KEYRING_CONTROL=/tmp/keyring-fmEhLa GTK_MODULES=canberra-gtk-module hi=hello #看到这个家伙了么?没错,就是刚刚用export导出的环境变量。 USER=neeo LS_COLORS=rs=0:di=01;34:ln=01;36:hl=44;37:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01: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:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=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:*.o: #------------此处省略无数字---------------
export不加参数,列出所有被export成环境变量的变量。
neeo@neeo-labtop:~$ export | less #同样,用less查看export的结果。 #---------------下面是结果------------- declare -x COLORTERM="gnome-terminal" declare -x DBUS_SESSION_BUS_ADDRESS="unix:abstract=/tmp/dbus-aLW92yDkwV,guid=7bd3671bf9dbe59601cdec5b50b9931c" declare -x DEFAULTS_PATH="/usr/share/gconf/gnome.default.path" declare -x DESKTOP_SESSION="gnome" declare -x DISPLAY=":0.0" declare -x GDMSESSION="gnome" declare -x GDM_KEYBOARD_LAYOUT="us" declare -x GDM_LANG="zh_CN.utf8" declare -x GNOME_DESKTOP_SESSION_ID="this-is-deprecated" declare -x GNOME_KEYRING_CONTROL="/tmp/keyring-fmEhLa" declare -x GNOME_KEYRING_PID="1891" declare -x GOARCH="386" declare -x GOBIN="/home/neeo/go/bin/" declare -x GOOS="linux" declare -x GOROOT="/home/neeo/go" declare -x GTK_IM_MODULE="xim" declare -x GTK_MODULES="canberra-gtk-module" declare -x HOME="/home/neeo" declare -x LANG="zh_CN.utf8" #------------此处又省略了无数字---------------------
等等,茫茫人海,我们之前定义的hi哪里去了呢?这货八成被省略了。。。。
neeo@neeo-labtop:~$ export | grep \ hi #让他无所遁形 declare -x hi="hello" #这货就是我们之前定义的hi了。 neeo@neeo-labtop:~$
env和export查看的结果基本没差别,那么,如果想要看到所有变量该怎么办呢?答案是set。
neeo@neeo-labtop:~$ set | less #用less查看set的结果, #------------------此处省略所有字----------------------- neeo@neeo-labtop:~$ set | grep ^BASH= #用set查看 BASH变量(BASH是系统自带的一个环境变量)。 BASH=/bin/bash neeo@neeo-labtop:~$ set | grep ^hi #用set查看刚刚定义的hi变量(这货已经升级为环境变量了)。 hi=hello neeo@neeo-labtop:~$ newvar=newvar #重新定义一个新的变量。 neeo@neeo-labtop:~$ set | grep ^newvar #set可以查到newvar(还不是环境变量)。 newvar=newvar neeo@neeo-labtop:~$ env | grep newvar #evn只能列出环境变量,他查不到这个新来的家伙。 neeo@neeo-labtop:~$ export | grep newvar #export也无能为力。 neeo@neeo-labtop:~$
另外declare和typeset如果不接参数,和set的结果相同
neeo@neeo-labtop:~$ declare | grep BASH= BASH=/bin/bash neeo@neeo-labtop:~$ typeset | grep BASH= BASH=/bin/bash neeo@neeo-labtop:~$
同样 readonly不接参数可以列出所有readonly变量。
neeo@neeo-labtop:~$ normal=normal neeo@neeo-labtop:~$ readonly normal neeo@neeo-labtop:~$ readonly | grep normal declare -r normal="normal" neeo@neeo-labtop:~$
如果某些变量非常常用,但每次启动shell都要重新定义就变得非常讨厌,解决办法是有的,但要先说说shell启动之前都干了些什么。
/etc/profile ,~/.bash_profile ,~/.bash_login ,~/.profile,~/.bashrc 以上文件,按先后顺序,如果存在就读入,否则跳过。
看到这里应该想到了,如果把变量定义的语句添加到这些文件中的一个,就可以实现每次启动都自动定义变量了(这篇的alias中已经提到了)
例如设置GO语言的环境变量可以在~/.bashrc文件中添加这样的代码
export GOROOT=~/go export GOARCH=386 export GOOS=linux export GOBIN=$GOROOT/bin/ export PATH=$PATH:$GOBIN export PATH=$PATH:$GOROOT/pkg/tool/linux_386/
这篇好乱,更多有关set,export,env的区别请看这里,其实最好的办法是找man!