与各种高级程序设计语言相似,shell环境下也可以一组文字或符号,来替换一些设置或者是一串保留的数据,这组文字或符号便是shell变量。
在linux环境中,存在大量不同的shell变量,既有环境本身自带的系统变量,也有用户自定义的普通变量。根据前面常用命令,我们可以用set命令查看linux系统当前所有变量及其内容。
[root@localhost test]# set
BASH=/bin/bash
BASH_ARGC=()
BASH_ARGV=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSION='3.00.15(1)-release'
COLORS=/etc/DIR_COLORS.xterm
COLORTERM=gnome-terminal
……
TERM=xterm
UID=0
USER=root
WINDOWID=50342033
XAUTHORITY=/root/.Xauthority
XMODIFIERS=@im=htt
_=--color=tty
下面作者根据使用功能不同将shell变量中常用的用户自定义变量、位置参数与环境变量三大块作详细分析。
1. 自定义变量
定义:变量名=变量值
在使用变量之前不需要事先声明,只需要通过“=”给它们赋初始值便可使用。但等号两边不能留空格,若一定要出现空格,就要用双引号括起来。
如:
[root@localhost shell]# myname=jingzhao
此时系统便定义了myname这个内容为jingzhao的变量
查看变量内容:在变量名前面加上一个$符号,再用echo命令将其内容输出到终端上。如:
[root@localhost shell]# echo $myname
Jingzhao
此时可以看到前面定义好的变量myname的内容jingzhao,同样方法可以查看系统己有的变量。如:
[root@localhost shell]# echo $HOME
/root
取消变量:利用“unset 变量”可以取消系统中己有变量。
如:
[root@localhost shell]# echo $myname
jingzhao
[root@localhost shell]# unset myname
[root@localhost shell]# echo $myname
[root@localhost shell]#
创建全局变量:在此之前所创建的变量均为当前shell下的局部变量,不能被其它shell利用。因此可以使用“export 变量名”将局部变量转化为全局变量,也可以直接利用“export 变量名=变量值”来创建一个全局变量。
如:
[root@localhost shell]# myname=jingzhao
[root@localhost shell]# echo $myname
jingzhao
[root@localhost shell]# bash
[root@localhost shell]# echo $myname
[root@localhost shell]# exit
exit
[root@localhost shell]# export myname
[root@localhost shell]# bash
[root@localhost shell]# echo $myname
jingzhao
[root@localhost shell]# ps
PID TTY TIME CMD
12528 pts/1 00:00:00 bash
16815 pts/1 00:00:00 bash
16831 pts/1 00:00:00 ps
[root@localhost shell]#
2. 位置参数变量
在linux/UNIX系统中,shell脚本执行时是可以带实参的。这些实参在脚本执行期间将会被赋予系统中自动定义好的一类变量中,这类变量就是位置参数变量。
命令行实参与脚本中位置参数变量的对应关系如下所示:
Exam m1 m2 m3 m4
$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
$ 0 : 获取(包含)脚本名称
$1 - $9 :获取(包含)第1至第9个参数
${ }: 获取第9个以上参数
$# :表示传给脚本或者函数的位置参数的个数(不包括”$0”)
$ *:所有位置参数的列表,形式是一个单个字符串,串中第1个参数由第1个字符串分隔。
$@:所有位置参数被分别表示为双引号中的N(参数个数 --- 不含$0)个字符串。
例如:[root@localhost ~]# echo one two three
分析:有4个位置参数 ---à 1个命令名( echo ) + 3个参量( one、two和three )
$0 = echo $1 = one $2 = two $3 = three
从上面对位置参数的解析中,我们可以发现:
(1)如果执行shell脚本时没有传递任何实参,$0(脚本名称)、$#(为0)等也存在,而$1、$2等则不存在。等脚本执行完毕,位置参数又恢复回系统初始值。
实验:
[root@localhost test]# vi sh.sh
#!/bin/bash
echo "first_parameter= $1"
echo "second_parameter=$2"
echo "third_parameter=$3"
echo "count_num=$#"
echo "all_parameter*=$*"
echo "all_parameter@=$@"
运行脚本执行如下:
[root@localhost test]# ./sh.sh yang jing zhao
first_parameter= yang
second_parameter=jing
third_parameter=zhao
count_num=3
all_parameter*=yang jing zhao
all_parameter@=yang jing zhao
(2)“$ *”和“$@”均可以表示所有位置参数,但它们之间却存在着很大的不同,这种不同允许你用两种方法来处理命令行参数。第一种“$ *”,因为它是一个单个字符,所以可以不需要很多shell代码来显示它,相比之下更加录活。第二种“$@”,它允许你独立处理每个参数,因为它的值是N个分离参数。
实验:
[root@localhost test]# vi bash.sh
#!/bin/bash
function cntparm
{
echo -e "inside cntparm: $# parms: $@\n"
}
echo -e "outside cntparm: $*\n"
echo -e "outside cntparm: $@\n"
cntparm "$*"
cntparm "$@"
运行脚本执行如下:
[root@localhost test]# ./bash.sh yang jing zhao
outside cntparm: yang jing zhao
outside cntparm: yang jing zhao
inside cntparm: 1 parms: yang jing zhao
inside cntparm: 3 parms: yang jing zhao
程序分析:(结合来整理)
函数第一次使用“$ *”,它把位置参数作为单个字符串,所以cntparm打印只有一个参数。但是第二次调用cntparm,把脚本的命令行参数当作了三个字符串,所以cntparm报告了三个参数。在打印的时候,参数的外观没有任何区别,最后两行输出清楚地表明了这一点。
Echo命令的-e选项强行要求它把字符串序列\n当作一个新行。如果没有-e选项,就不要用\n来产生一个新行,因为echo会自动地在输出后面加上一个\n。
(3)在执行shell程序时,位置参数变量并不是固定不变的,利用set 命令可以为位置参数赋值或重新赋值。其格式为:
Set paramet1 paramet2 paramet3
实验:
[root@localhost test]# vi sh.sh
#!/bin/bash
echo "first_parameter= $1"
echo "second_parameter=$2"
echo "third_parameter=$3"
set one two three
echo "parameters chance:"
echo "first_parameter= $1"
echo "second_parameter=$2"
echo "third_parameter=$3"
运行脚本执行如下:
[root@localhost test]# ./sh.sh yang jing zhao
first_parameter= yang
second_parameter=jing
third_parameter=zhao
parameters chance:
first_parameter= one
second_parameter=two
third_parameter=three
3. 环境变量
在用户注册过程(会话建立过程)中系统需要做的一件事就是建立用户环境。所有的linux进程都有各自独立,并且不同于程序本身的环境。Linux环境由许多变量及这些变量的值组成。这些变量及变量的值决定了用户环境的外观。
Shell环境包括使用的shell类型、主目录所在位置及正在使用的终端类型等多方面的内容。决定这些内容的变量有许多是在注册过程中定义的,一些为只读,意味着不能改变这些变量;而一般为非只读变量,可以随意增加或修改。(要做修改哦)
(1)常用环境变量
当一个shell开始执行时,一些变量会根据环境设置中的值进行初始化。我们的shell脚本程序就是根据这些初始化的环境变量来解析运行。
在bash、sh及ksh中,可以利用env或export命令查看系统中环境变量如下:
[root@localhost test]# env
SSH_AGENT_PID=5025
HOSTNAME=localhost.localdomain
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
WINDOWID=50342033
USER=root
。。。。。。
LESSOPEN=|/usr/bin/lesspipe.sh %s
DISPLAY=:0.0
GTK_IM_MODULE=iiim
G_BROKEN_FILENAMES=1
COLORTERM=gnome-terminal
XAUTHORITY=/root/.Xauthority
_=/bin/env
OLDPWD=/root/shell/test
(2)环境文件(鼠标右击打开终端是要重新去读取一次环境文件)
上面用env所查看到的均为环境变量及其内容,这些变量都是通过系统中一系列脚本来配置完成的。从系统起来到用户注册进入系统,shell会读取一系列称为脚本的环境文件,并执行其中命令。常见的环境文件包括:
系统级:
/etc/profile:初始化一些基本的环境变量,并执行/etc/profile.d/目录下的脚本引导系统进一步启动,在系统启动会话时被调用
/etc/bashrc:保存一些变量设置并执行/etc/profile.d/目录下脚本的命令,每次打开终端时会被.bashrc调用
/etc/profile.d:包含了配置特别程序的跨系统行为的文件
/etc/inputrc:配置命令行响铃风格的跨系统的行读取初始化文件
用户级:(每个用户均有独立的配置文件,在此以超级用户root为例)
.bash_history:记录用户以前输入的命令
.bash_logout:用户退出注册时执行的命令
.bash_profile:功能同上面系统级一样,只是属于具体同户
.bashrc:功能同上面系统级一样,只是属于具体同户
从系统启动到用户登录bash shell,上面的环境文件是控照一定的先后顺序来读取的。
首先读取/etc/profile,根据/etc/profile中的内容去执行相关命令或读取其它附加的环境文件,如/etc/profile.d、/etc/inputrc等,根据其中内容搭建起基本的系统环境。根据不同用户,到/home目录去读取.bash_profile,根据内容执行相关命令并读取.bashrc以搭建起满足不同用户的环境。
下面将就主要环境变量的使用举例说明。
PATH:搜索路径环境变量。
定义:Shell从中查找命令的目录列表.它是一个非常重要的shell变量。PATH变量包含带冒号分界符的字符串,这些字符串指向含有你所使用命令。(可以补充常用的命令目录)
查看PATH变量内容
[root@localhost ~]# 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
2)修改PATH变量
因PATH是命令搜索路径的环境变量,所以修改变量时不能替换变量,只能采用添加的方式,如主目录下有一个jingzhao目录,存放你编写的所有可执行命令,要把这个目录加到PATH变量中,可以输入以下命令行:
[root@localhost ~]# 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
[root@localhost ~]# PATH=$HOME/jingzhao
[root@localhost ~]# echo $PATH
/root/directory
[root@localhost ~]# ls
bash: ls: command not found
修改后,除了bash shell内置命令外,其它外部命令再也无法使用,主要是外部命令的搜索路径被新的变量替代。所以,应该如下修改:
[root@localhost ~]# 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
[root@localhost ~]# PATH=$PATHHOME/jingzhao
[root@localhost ~]# 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:/root/directory
[root@localhost shell]# ls
achievements_file applicate.sh students_file test
至此,只是为当前终端设置了新的“$PATH”变量,如果打开一个新的终端,运行“echo $PATH”,显示的还是没修改前的“$PATH”值。因为先前重新定义的是一个局部环境变量,只能作用在当前终端。
要将其定义为一个全局变量,使其在以后打开的终端中生效,可以采用export来定义并将其写入配置文件实现。/etc/profile与.bash_profile在/root下只在会话时被读取一次,因此常用来设置不常变化的环境变量,如PATH等。而.bashrc与/etc/bashrc则在每次打开终端时都要被读取一次,故可以用来配置一些个性设置,如终端字体大小、色调等等。
[root@localhost ~]# vi .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATHHOME/bin
export PATH
unset USERNAME
export PATH=$PATHHOME/jingzhao
保存退出后,重新打开一个新的终端,键入“echo $PATH”,屏幕上显示的还是修改前的“$PATH”,这是怎么回事呢?原来/etc/profile与.bash_profile只在会话时被读取一次,所以必须重启机器让会话进行一次。
[root@localhost ~]# reboot
随后在重启后的机器中再次键入“echo $PATH”,这次可以看到修改后的变量了。
[root@localhost ~]# 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:/root/jingzhao
如果不想每次修改完PATH后都要重启,而且打开新的终端也能应用修改后的变量,就只能在.bashrc与/etc/bashrc环境文件中修改了。
[root@localhost ~]# vi .bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
export PATH=$HOME/jingzhao
保存退出后查看下变量
[root@localhost ~]# 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
执行 source命令
[root@localhost ~]# source .bashrc
再次查看变量内容
[root@localhost ~]# 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:/root/jingzhao
另外打开一个新的终端也可以看到变量己修改。但这样做也会存在一个较为严重的问题,就是每次打开一个终端,文件被读取一次,目录也会添加一次,这样将导致PATH变量由于目录复制,不断地增长。如下示:
[root@localhost ~]# 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:/root/jingzhao
[root@localhost ~]# bash
[root@localhost ~]# ps
PID TTY TIME CMD
6459 pts/2 00:00:00 bash
6479 pts/2 00:00:00 bash
6508 pts/2 00:00:00 ps
[root@localhost ~]# 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:/root/jingzhao:/root/jingzhao
如果使用bash,可以把它加到.bash_profile文件中(环境文件),这样,它会在每次注册时起作用。一般情况下,PATH变量中往往有一个目录/usr/local/bin,这个目录中的命令不是linux标准的命令,而是由系统管理员添加和维护的、供所有用户使用的命令。如果PATH变量中不存在这个目录,你可以自己将它添加进去。
PS1:提示符:
每次当打开一个控制台时,最先看到的就是提示符,如下所示:
[root@localhost ~]#
在默认的设置下,提示符将显示用户名、主机名、当前所在目录(“~”表示用户的宿主目录),最后一个字符可以示识是普通用户($),还是root管理员(#)。
可以通过$PS1变量来设置提示符。如下命令将显示当前的设定值:
[root@localhost ~]# echo $PS1
[\u@\h \W]\$
上面这些符号都是什么呢 是PS1变量的值
PS1的值由一系列静态文本或\和转义字符序列组成:
比较有用的转义序列有:
\e ASCII转义字符
\h 主机名
\H 完整的主机名
\l 终端设备名
\t 24小时制时间
\T 12小时制时间
\u 用户名
\w 当前工作目录(绝对路径)
\W 当前工作目录(basename)
\! 当前命令在历史缓冲区的位置
\$ 如果当前用户是super user,则插入字符#;否则插入字符$
\[ 出现在不移动光标的字符序列之前
\] 出现在非打印字符之后
通过这些转义序列来设置PS1的值,可以将提示符进行个性化设置:
对于初学者来说,系统自带的一些设置有些不友好,因为提示符只显示当前目录的最后一部分。如果看到如下所示的提示符:
[root@localhost bin]#
当前目录可能是/bin、/usr/bin、/usr/local/bin或者是/me/X11R6/bin,只能用pwd命令来查看绝对路径。
能不能让shell自动告诉当前目录呢?
当然可以。这里将提到的设置,包括提示符,大都包含在文件/etc/bashrc中。可以通过编辑各用户/home目录下的“.bashrc_profile”和“.bashrc”文件来改变设置。
如下面基本设置可以看到绝对路径:
export PS1="[\w]\\$"
[~/vod/photo]#
此外,我们还可以设置提示符的颜色、当前时间、命令的历史记录等等
export PS1="\[\033[0;31m\][\w]\\$\[\033[0m\] "
[~/vod/photo]#(颜色改变)
2、环境变量设置
实验:如何设置一个新的PATH环境变量?
本文转载于唯C教育,【Linux基础】shell变量
http://www.weicedu.com/forum.php?mod=viewthread&tid=93&fromuid=4
(出处: http://www.weicedu.com/)
http://www.weicedu.com/forum.php?mod=viewthread&tid=93&fromuid=4
(出处: http://www.weicedu.com/)