内部变量的学习


内部变量的学习
 
内建变量,这些变量将会影响bash脚本的行为.
$BASH
 
Bash的二进制程序文件的路径
root@ubuntu:~/resource/shell-study/0506-2013# echo $BASH  
/bin/bash  
$BASH_ENV
这个环境变量会指向一个Bash的启动文件, 当一个脚本被调用的时候, 这个启动文件将会被读取.
 
$BASH_SUBSHELL
这个变量用来提示子shell的层次. 这是一个Bash的新特性, 直到版本3的Bash才被引入近来.
 
$BASH_VERSINFO[n]
这是一个含有6个元素的数组, 它包含了所安装的Bash的版本信息. 这与下边的$BASH_VERSION很相像, 但是这个更加详细一些.
root@ubuntu:~/resource/shell-study/0506-2013# for n in 0 1 2 3 4 5  
> do   
> echo "BASH_VERSINFO[$n] = ${BASH_VERSINFO[$n]}"  
> done  
BASH_VERSINFO[0] = 4  
BASH_VERSINFO[1] = 1  
BASH_VERSINFO[2] = 5  
BASH_VERSINFO[3] = 1  
BASH_VERSINFO[4] = release  
BASH_VERSINFO[5] = i486-pc-linux-gnu  
$BASH_VERSION
安装在系统上的Bash版本号
root@ubuntu:~/resource/shell-study/0506-2013# echo $BASH_VERSION  
4.1.5(1)-release  
这个输出的信息和上面通过数组查询到的信息是一一对应的
$DIRSTACK
在目录栈中最顶端的值. (将会受到pushd和popd的影响),这个内建变量与dirs命令相符, 但是dirs命令会显示目录栈的整个内容.
 
$EDITOR
脚本所调用的默认编辑器, 通常情况下是vi或者是emacs.
 
$EUID
"有效"用户ID,不管当前用户被假定成什么用户, 这个数都用来表示当前用户的标识号, 也可能使用su命令来达到假定的目的.,$EUID并不一定与$UID相同.
 
$FUNCNAME(当前函数的名字)
#!/bin/bash  
  
func ()  
{  
    echo "$FUNCNAME is running."  
}  
func  
echo "FUNCNAME = $FUNCNAME"  
  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0506-2013# ./test7.sh   
func is running.  
FUNCNAME =   
root@ubuntu:~/resource/shell-study/0506-2013#   
第二行没有name,因为FUNCNAME只能用在函数方法内部使用
$GLOBIGNORE
一个文件名的模式匹配列表, 如果在通配(globbing)中匹配到的文件包含有这个列表中的某个文件, 那么这个文件将被从匹配到的结果中去掉.
 
$GROUPS
目前用户所属的组,这是一个当前用户的组id列表(数组), 与记录在/etc/passwd文件中的内容一样
 
$HOME
用户的home目录, 一般是/home/usernam
 
$HOSTNAME
hostname放在一个初始化脚本中, 在系统启动的时候分配一个系统名字. 然而, gethostname()函数可以用来设置这个Bash内部变量$HOSTNAME
 
$HOSTTYPE
主机类型,就像$MACHTYPE, 用来识别系统硬件.
 
root@ubuntu:~/resource/shell-study/0506-2013# echo $HOSTNAME  
ubuntu  
root@ubuntu:~/resource/shell-study/0506-2013# echo $HOSTTYPE  
i486  
root@ubuntu:~/resource/shell-study/0506-2013# echo $HOME  
/root  
root@ubuntu:~/resource/shell-study/0506-2013# echo $GROUPS  
0  
root@ubuntu:~/resource/shell-study/0506-2013#   
$IFS
内部域分隔符,这个变量用来决定Bash在解释字符串时如何识别域, 或者单词边界.
$IFS默认为空白(空格, 制表符,和换行符), 但这是可以修改的, 比如, 在分析逗号分隔的数据文件时, 就可以设置为逗号. 注意$*使用的是保存在$IFS中的第一个字符
#!/bin/bash  
  
output_args_one_per_line()  
{  
    for arg  
    do echo "[$arg]"  
    done  
}  
  
echo "IFS=\" \""  
IFS=" "  
var=" a  b c   "  
output_args_one_per_line $var  
  
echo "----------------"  
echo "IFS=:"  
IFS=":"  
var=":a::b:c:::"  
output_args_one_per_line $var  
  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0506-2013# ./test8.sh   
IFS=" "  
[a]  
[b]  
[c]  
----------------  
IFS=:  
[]  
[a]  
[]  
[b]  
[c]  
[]  
[]  
root@ubuntu:~/resource/shell-study/0506-2013#   
可以看出还是挺奇怪的,当使用IFS=" "和使用“:”时,结果还是有些出入的,同样的事情也会发生在awk的"FS"域中.
$IGNOREEOF
忽略EOF: 告诉shell在log out之前要忽略多少文件结束符(control-D).
 
$LC_COLLATE
常在.bashrc或/etc/profile中设置, 这个变量用来控制文件名扩展和模式匹配的展开顺序. 如果$LC_COLLATE设置得不正确的话, LC_COLLATE会在文件名匹配(filename globbing)中产生不可预料的结果.
 
$LC_CTYPE
这个内部变量用来控制通配(globbing)和模式匹配中的字符串解释.
 
$LINENO
这个变量用来记录自身在脚本中所在的行号. 这个变量只有在脚本使用这个变量的时候才有意义, 并且这个变量一般用于调试目的.
 
$MACHTYPE
机器类型,标识系统的硬件.
 
$OLDPWD
之前的工作目录("OLD-print-working-directory", 就是之前你所在的目录)
 
$OSTYPE
操作系统类型
 
$PATH
可执行文件的搜索路径, 一般为/usr/bin/, /usr/X11R6/bin/, /usr/local/bin, 等等.
 
$PPID
进程的$PPID就是这个进程的父进程的进程ID(pid). [1]
 
$PROMPT_COMMAND
这个变量保存了在主提示符$PS1显示之前需要执行的命令.
 
$PS1
这是主提示符, 可以在命令行中见到它.
 
$PS2
第二提示符, 当你需要额外输入的时候, 你就会看到它. 默认显示">".
 
$PS3
第三提示符, 它在一个select循环中显示(参见例子 10-29).
 
$PS4
第四提示符, 当你使用-x选项来调用脚本时, 这个提示符会出现在每行输出的开头. 默认显示"+".
 
$PWD
工作目录(你当前所在的目录),这与内建命令pwd作用相同.
 
$REPLY
当没有参数变量提供给read命令的时候, 这个变量会作为默认变量提供给read命令. 也可以用于select菜单, 但是只提供所选择变量的编号, 而不是变量本身的值
#!/bin/bash  
# REPLY是提供给'read'命令的默认变量.  
  
echo -n "What is your favorite vegetable? "  
read  
echo "Your favorite vegetable is $REPLY."  
#  当且仅当没有变量提供给"read"命令时, REPLY才保存最后一个"read"命令读入的值.  
  
echo -n "What is your favorite fruit? "  
read fruit  
echo "Your favorite fruit is $fruit."  
echo "but...Value of \$REPLY is still $REPLY."  
#  $REPLY还是保存着上一个read命令的值,  
#+ 因为变量$fruit被传入到了这个新的"read"命令中.  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0506-2013# ./test9.sh   
What is your favorite vegetable?   
Your favorite vegetable is .  
What is your favorite fruit? apple  
Your favorite fruit is apple.  
but...Value of $REPLY is still .  
root@ubuntu:~/resource/shell-study/0506-2013#   
$SECONDS
这个脚本已经运行的时间(以秒为单位).
#!/bin/bash  
TIME_LIMIT=10  
INTERVAL=1  
echo "Hit Control-C to exit before $TIME_LIMIT seconds."  
while [ "$SECONDS" -le "$TIME_LIMIT" ]  
do  
    if [ "$SECONDS" -eq 1 ];then  
        units=second  
    else    
        units=seconds  
    fi  
    echo "This script has been running $SECONDS $units."  
    #  在一台比较慢或者是附载过大的机器上,在单次循环中, 脚本可能会忽略计数.   
    sleep $INTERVAL  
done  
echo -e "\a"  # Beep!(哔哔声!)  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0506-2013# ./test10.sh   
Hit Control-C to exit before 10 seconds.  
This script has been running 0 seconds.  
This script has been running 1 second.  
This script has been running 2 seconds.  
This script has been running 3 seconds.  
This script has been running 4 seconds.  
This script has been running 5 seconds.  
This script has been running 6 seconds.  
This script has been running 7 seconds.  
This script has been running 8 seconds.  
This script has been running 9 seconds.  
This script has been running 10 seconds.  
  
root@ubuntu:~/resource/shell-study/0506-2013#   
$SHELLOPTS
shell中已经激活的选项的列表, 这是一个只读变量.
bash$ echo $SHELLOPTS
braceexpand:hashall:histexpand:monitor:history:interactive-comments:emacs
 
$SHLVL
Shell级别, 就是Bash被嵌套的深度. 如果是在命令行中, 那么$SHLVL为1, 如果在脚本中那么$SHLVL为2.
 
$TMOUT
如果$TMOUT环境变量被设置为非零值time的话, 那么经过time秒后, shell提示符将会超时. 这将会导致登出(logout).
#!/bin/bash  
  
#TMOUT=3  
TIMELIMIT=5  
  
PrintAnswer()  
{  
    if [ "$answer" = TIMEOUT ];then  
        echo $answer  
    else  
        echo "Your favorite veggie is $answer"  
        kill $!  
    fi  
}  
  
TimerOn()  
{  
    sleep $TIMELIMIT && kill -s 14 $$ &  
}  
  
Int14Vector()  
{  
    answer="TIMEOUT"  
    PrintAnswer  
    exit 14  
}  
  
trap Int14Vector 14  
echo "What is your favorite vegetable"  
TimerOn  
read answer  
PrintAnswer  
  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0506-2013# ./test11.sh   
What is your favorite vegetable  
TIMEOUT  
root@ubuntu:~/resource/shell-study/0506-2013# ./test11.sh   
What is your favorite vegetable  
all  
Your favorite veggie is all  
root@ubuntu:~/resource/shell-study/0506-2013# ^C  
$UID
用户ID号,当前用户的用户标识号, 记录在/etc/passwd文件中,这是当前用户的真实id, 即使只是通过使用su命令来临时改变为另一个用户标识, 这个id也不会被改变. $UID是一个只读变量, 不能在命令行或者脚本中修改它, 并且和id内建命令很相像.
#!/bin/bash  
  
ROOT_UID=0  
if [ "$UID" -eq "$ROOT_UID" ];then  
    echo "You are root."  
else  
    echo "You are just an ordinary user."  
fi  
  
ROOTUSER_NAME=root  
username=`whoami`  
#username=`id -nu`  
if [ "$username" = "$ROOTUSER_NAME" ];then  
    echo "You are root."  
else  
    echo "You are just an ordinary user."  
fi  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0507-2013# chmod +x test1.sh   
root@ubuntu:~/resource/shell-study/0507-2013# ./test1.sh   
You are root.  
You are root.  
位置参数
$0, $1, $2, 等等
 
位置参数, 从命令行传递到脚本, 或者传递给函数, 或者set给变量
 
$#
命令行参数或者位置参数的个数
$*
所有的位置参数都被看作为一个单词,"$*"必须被引用起来.
$@
与$*相同, 但是每个参数都是一个独立的引用字符串, 这就意味着, 参数是被完整传递的, 并没有被解释或扩展. 这也意味着, 参数列表中每个参数都被看作为单独的单词,当然, "$@"应该被引用起来.
#!/bin/bash  
  
E_BADARGS=65  
if [ ! -n "$1" ];then  
    echo "usage: `basename $0` args1 args2 etc."  
    exit $E_BADARGS  
fi  
  
index=1  
echo "Listing args with \"\$*\""  
for arg in "$*"  
do   
    echo "arg#$index = $arg"  
    let "index+=1"  
done  
echo "entire arg list seen as single word."  
  
index=1  
echo "Listing args with \"\$@\""  
for arg in "$@"  
do  
    echo "arg #$index = $arg"  
    let "index+=1"  
done  
echo "arg list seen as separate words."  
  
index=1  
echo "Listing args with \$* (unquoted):"  
for arg in $*  
do  
    echo "arg #$index = $arg"  
    let "index+=1"  
done  
echo "Arg list seen as separate words."  
  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0507-2013# ./test2.sh 1 2 34  
Listing args with "$*"  
arg#1 = 1 2 34  
entire arg list seen as single word.  
Listing args with "$@"  
arg #1 = 1  
arg #2 = 2  
arg #3 = 34  
arg list seen as separate words.  
Listing args with $* (unquoted):  
arg #1 = 1  
arg #2 = 2  
arg #3 = 34  
Arg list seen as separate words.  
root@ubuntu:~/resource/shell-study/0507-2013#  
shift的用法说明:
 
#!/bin/bash  
echo "$@"  
shift  
echo "$@"  
shift  
echo "$@"  
结果;
root@ubuntu:~/resource/shell-study/0507-2013# ./test3.sh 1 2 3 4 5 6  
1 2 3 4 5 6  
2 3 4 5 6  
3 4 5 6  
root@ubuntu:~/resource/shell-study/0507-2013#   
$-
传递给脚本的标记(使用set命令). 参见例子 11-15.
这本来是ksh的结构, 后来被引进到Bash中, 但是不幸的是, 看起来它不能够可靠的用在Bash脚本中. 一种可能的用法是让一个脚本测试自身是不是可交互的.
$!
运行在后台的最后一个作业的PID(进程ID)
$_
这个变量保存之前执行的命令的最后一个参数的值.
#!/bin/bash  
echo $_              # /bin/bash  
du >/dev/null        # 这么做命令行上将没有输出.  
echo $_              # du  
ls -al >/dev/null    # 这么做命令行上将没有输出.  
echo $_              # -al  (这是最后的参数)  
   
:  
echo $_   
结果:
root@ubuntu:~/resource/shell-study/0507-2013# ./test4.sh   
./test4.sh  
du  
-al  
:  
root@ubuntu:~/resource/shell-study/0507-2013#   
$?
命令, 函数, 或者是脚本本身的退出状态码
#!/bin/bash  
  
echo $?  
  
cat file #wrong command  
echo $?  
  
echo "right command."  
echo $?  
exit 0  
结果:
root@ubuntu:~/resource/shell-study/0507-2013# ./test5.sh   
0  
cat: file: No such file or directory  
1  
right command.  
0  
root@ubuntu:~/resource/shell-study/0507-2013#   
 
$$
脚本自身的进程ID. $$变量在脚本中经常用来构造"唯一的"临时文件名

相关内容

    暂无相关文章