bash$echo"$IFS"(当 $IFS 设置为缺省值时,显示空行。)bash$echo"$IFS"|cat-vte^I$$(显示空白符:首先是一个空格,然后是^I [水平制表符],然后是换行符,最后在末尾显示"$"。)bash$bash-c'set w x y z; IFS=":-;"; echo "$*"'w:x:y:z(从字符串中解析命令,然后将命令参数分配给位置参数。)
通过设置 $IFS 来忽略文件路径名中空格带来的影响。
IFS="$(printf '\n\t')"# 按 David Wheeler 所述。
相比于其他字符,变量 $IFS 在处理空白符时有所不同。
样例 9-1. $IFS 与空白符
#!/bin/bash# ifs.shvar1="a+b+c"var2="d-e-f"var3="g,h,i"IFS=+# 加号会被解析成分隔符。echo $var1 # a b cecho $var2 # d-e-fecho $var3 # g,h,iechoIFS="-"# 恢复对加号的默认解析。# 现在减号会被解析成分隔符。echo $var1 # a+b+cecho $var2 # d e fecho $var3 # g,h,iechoIFS=","# 现在逗号会被解析成分隔符。# 恢复对减号的默认解析。echo $var1 # a+b+cecho $var2 # d-e-fecho $var3 # g h iechoIFS=" "# 现在空格会被解析成分隔符。# 逗号恢复成默认解析。echo $var1 # a+b+cecho $var2 # d-e-fecho $var3 # g,h,i# ======================================================== ## 然而...# $IFS 处理空白符的方式不同其他字符。output_args_one_per_line(){for argdoecho"[$arg]"done# ^ ^ 为了获得更好的视觉体验,把参数放到了括号里。}echo; echo"IFS=\" \""echo"-------"IFS=" "var=" a b c "# ^ ^^ ^^^output_args_one_per_line $var # output_args_one_per_line `echo " a b c "`# [a]# [b]# [c]echo; echo"IFS=:"echo"-----"IFS=:var=":a::b:c:::"# 与上面一样的模式,# ^ ^^ ^^^ #+ 仅仅是将 " " 替换成了 ":" ...output_args_one_per_line $var# []# [a]# []# [b]# [c]# []# []# 注意那些“空的”括号。# 同样的情况也会出现在 awk 命令所使用的 "FS" 字段分隔符中。echoexit
#!/bin/bash# reply.sh# REPLY 是 'read' 命令的默认接收参数。echoecho-n"What is your favorite vegetable? "readecho"Your favorite vegetable is $REPLY."# 当且仅当 'read' 命令没有接收参数的时候,#+ REPLY 才能保存最近一次 'read' 命令接收的值。echoecho-n"What is your favorite fruit? "readfruitecho"Your favorite fruit is $fruit."echo"but..."echo"Value of \$REPLY is still $REPLY."# 因为变量 $fruit 接收了新一次 "read" 命令所读入的值,#+ 所以 $REPLY 仍旧存储的是上一次接收的值。echoexit0
$SECONDS
该变量记录到目前为止脚本执行的时间,单位为秒。
#!/bin/bashTIME_LIMIT=10INTERVAL=1echoecho"Hit Control-C to exit before $TIME_LIMIT seconds."echowhile [ "$SECONDS"-le"$TIME_LIMIT" ]do# $SECONDS 是一个 shell 的内部变量。if [ "$SECONDS"-eq1 ]then units=secondelse units=secondsfiecho"This script has been running $SECONDS $units."# 在一台性能较差或负载过重的设备上,#+ 这个脚本可能会偶尔跳过几个计数。sleep $INTERVALdoneecho-e"\a"# 发出蜂鸣声!exit0
# 只能在 Bash 2.05b 及之后的版本中成功执行。TMOUT=3# 提示会在 3 秒后超时。echo"What is your favorite song?"echo"Quickly now, you only have $TMOUT seconds to answer!"readsongif [ -z"$song" ]then song="(no answer)"# 默认值。fiecho"Your favorite song is $song."
该 ID 表示的是当前用户的真实 ID,即使用户通过 su 命令临时切换至另一个用户,这个 ID 也不会改变。$UID 是一个只读变量,不能够被命令行或是脚本中的命令所修改,并与内建命令 id 相对应。
样例 9-5. 我是 root 用户吗?
#!/bin/bash# am-i-root.sh: 我是否是 root 用户?ROOT_UID=0# Root 用户的 $UID 为 0。if [ "$UID"-eq"$ROOT_UID" ] # 只有真正的 "root" 用户才能经受得住考研。thenecho"You are root."elseecho"You are just an ordinary user (but mom loves you just the same)."fiexit0# ============================================================= ## 下面的代码将不会被执行,因为脚本已经退出了。# 另外一种判断是否是 root 用户的方法:ROOTUSER_NAME=rootusername=`id-nu`# 或是... username=`whoami`if [ "$username"="$ROOTUSER_NAME" ]thenecho"Rooty, toot, toot. You are root."elseecho"You are just a regular fella."fi
#!/bin/bash# arglist.sh# 在调用该脚本时需要跟上一些参数,例如 "one two three" ...E_BADARGS=85if [ !-n"$1" ]thenecho"Usage: `basename $0` argument1 argument2 etc."exit $E_BADARGSfiechoindex=1# 初始化计数器。echo"Listing args with \"\$*\":"for arg in"$*"# 如果这里没有引用 "$*",脚本将不会正常运行。doecho"Arg #$index = $arg"let"index+=1"done# $* 将所有参数视作一个单词。echo"Entire arg list seen as single word."echoindex=1# 重置计数器。# 如果忘了这一步将会发生什么?echo"Listing args with \"\$@\":"for arg in"$@"doecho"Arg #$index = $arg"let"index+=1"done# $@ 将所有参数视作独立的单词。echo"Arg list seen as separate words."echoindex=1# 重置计数器。echo"Listing args with \$* (unquoted):"for arg in $*doecho"Arg #$index = $arg"let"index+=1"done# 未被引用的 $* 将所有参数视作独立的单词。echo"Arg list seen as separate words."exit0
#!/bin/bash# Bash 的内部变量 "$*" 和 "$@" 拥有不稳定的行为,#+ 这些行为是否出现通常依赖于它们是否是被引用的状态。# 下面的代码会演示在分词和换行时,这些变量所会出现的一些不一致的处理方式。set--"First one""second""third:one""""Fifth: :one"# 设置脚本参数,$1, $2, $3 等等。echoecho'IFS unchanged, using "$*"'c=0for i in"$*"# 被引用状态。doecho"$((c+=1)): [$i]"# 这一行在下面所有的例子中都保持不变。# 输出参数。doneecho---echo'IFS unchanged, using $*'c=0for i in $* # 未被引用状态。doecho"$((c+=1)): [$i]"doneecho---echo'IFS unchanged, using "$@"'c=0for i in"$@"doecho"$((c+=1)): [$i]"doneecho---echo'IFS unchanged, using $@'c=0for i in $@doecho"$((c+=1)): [$i]"doneecho---IFS=:echo'IFS=":", using "$*"'c=0for i in"$*"doecho"$((c+=1)): [$i]"doneecho---echo'IFS=":", using $*'c=0for i in $*doecho"$((c+=1)): [$i]"doneecho---var=$*echo'IFS=":", using "$var" (var=$*)'c=0for i in"$var"doecho"$((c+=1)): [$i]"doneecho---echo'IFS=":", using $var (var=$*)'c=0for i in $vardoecho"$((c+=1)): [$i]"doneecho---var="$*"echo'IFS=":", using $var (var="$*")'c=0for i in $vardoecho"$((c+=1)): [$i]"doneecho---echo'IFS=":", using "$var" (var="$*")'c=0for i in"$var"doecho"$((c+=1)): [$i]"doneecho---echo'IFS=":", using "$@"'c=0for i in"$@"doecho"$((c+=1)): [$i]"doneecho---echo'IFS=":", using $@'c=0for i in $@doecho"$((c+=1)): [$i]"doneecho---var=$@echo'IFS=":", using $var (var=$@)'c=0for i in $vardoecho"$((c+=1)): [$i]"doneecho---echo'IFS=":", using "$var" (var=$@)'c=0for i in"$var"doecho"$((c+=1)): [$i]"doneecho---var="$@"echo'IFS=":", using "$var" (var="$@")'c=0for i in"$var"doecho"$((c+=1)): [$i]"doneecho---echo'IFS=":", using $var (var="$@")'c=0for i in $vardoecho"$((c+=1)): [$i]"doneecho# 尝试在 ksh 或是 zsh -y 下执行这个脚本。exit0# 这个样例是由 Stephane Chazelas 所编写,#+ 由本书作者轻微改动。