高级Bash脚本编程指南(10):内部变量

高级Bash脚本编程指南(10):内部变量

成于坚持,败于止步

内建变量,这些变量将会影响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. $$变量在脚本中经常用来构造"唯一的"临时文件名

先到这里了,O(∩_∩)O~

我的专栏地址:http://blog.csdn.net/column/details/shell-daily-study.html

待续。。。。。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值