概述
17. /dev/null
$ ls my.file no.such.file 2>/dev/null
my.file
若要相反:只想看到 stderr 呢?还不简单﹗将 stdout 弄到 null 就行:
$ ls my.file no.such.file >/dev/null
ls: no.such.file: No such file or directory
除了用 >/dev/null 2>&1 之外,你还可以如此:
$ ls my.file no.such.file &>/dev/null
(提示:将 &> 换成 >& 也行啦~~! )
再问:那... 有办法不取消而又"临时"盖写目标档案吗?
$ set -o noclobber
$ echo "6" >| file.out
$ cat file.out
6
留意到没有:在 > 后面再加个" | "就好(注意: > 与 | 之间不能有空白哦)....
再来还有一个难题要你去参透的呢:
$ echo "some text here" > file
$ cat < file
some text here
$ cat < file > file.bak
$ cat < file.bak
some text here
$ cat < file > file
$ cat < file
---- 怎么最后那个 cat 命令看到的 file 竟是空的?﹗
$ cat < file > file 之后原本有内容的档案结果却被洗掉了﹗
这只是 priority 的问题而已
* 在 IO Redirection 中,stdout 与 stderr 的管道会先准备好,才会从 stdin 读进资料。
file 会先将 file 清空,然后才读进 < file ,
但这时候档案已经被清空了,因此就变成读不进任何资料了...
在 pipe line 之间,前一个命令的 stderr 是不会接进下一命令的 stdin 的,
其输出,若不用 2> 导到 file 去的话,它还是送到监视器上面来﹗
这点请你在 pipe line 运用上务必要注意的。
* 在 cm1 | cm2 | cm3 ... 这段 pipe line 中,若要将 cm2 的结果存到某一档案呢?
若你写成 cm1 | cm2 > file | cm3 的话,
那你肯定会发现 cm3 的 stdin 是空的﹗(当然啦,你都将水管接到别的水池了﹗)
cm1 | cm2 > file ; cm3 < file
cm1 | cm2 > file ; cm3 < file
有的,那就是 tee 命令了。
* 所谓 tee 命令是在不影响原本 I/O 的情况下,将 stdout 复制一份到档案去。
因此,上面的命令行可以如此打:
cm1 | cm2 | tee file | cm3
18. 你要 if 还是 case 呢?
comd1 && {
comd2
comd3
} || {
comd4
comd5
}
若你记得 return value ,我想你也应该记得了 && 与 || 是甚么意思吧?
用这两个符号再配搭 command group 的话,我们可让 shell script 变得更加聪明哦。
假如 comd1 的 return value 为 true 的话,
然则执行 comd3 与 comd4 ,
否则执行 comd4 与 comd5 。
改成if then else
if comd1
then
comd2
comd3
else
comd4
comd5
fi
可使用 elif 这样的 keyword :
if comd1; then
comd2
elif comd3; then
comd4
else
comd5
fi
若 comd1 为 true ,然则执行 comd2 ﹔
否则再测试 comd3 ,然则执行 comd4 ﹔
倘若 comd1 与 comd3 均不成立,那就执行 comd5 。
虽然 if 判断式已可应付大部份的条件执行了,然而,在某些场合中,却不够灵活,
尤其是在 string 式样的判断上,比方如下:
QQ () {
echo -n "Do you want to continue? (Yes/No): "
read YN
if [ "$YN" = Y -o "$YN" = y -o "$YN" = "Yes" -o "$YN" = "yes" -o "$YN" = "YES" ]
then
else
exit 0
fi
}
从例中,我们看得出来,最麻烦的部份是在于判断 YN 的值可能有好几种式样。
..
if echo "$YN" | grep -q '^[Yy]([Ee][Ss])*$'
QQ () {
echo -n "Do you want to continue? (Yes/No): "
read YN
case "$YN" in
[Yy]|[Yy][Ee][Ss])
;;
*)
exit 0
;;
esac
}
我们常 case 的判断式来判断某一变量在同的值(通常是 string)时作出不同的处理,
比方说,判断 script 参数以执行不同的命令。
若你有兴趣、且用 Linux 系统的话,不妨挖一挖 /etc/init.d/* 里那堆 script 中的 case 用
法。
case "$1" in
start)
start
;;
stop)
stop
;;
status)
rhstatus
;;
restart|reload)
restart
;;
condrestart)
[ -f /var/lock/subsys/syslog ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart}"
exit 1
esac
18.最后要介绍的是 shell script 设计中常见的"循环"(loop)。
bash shell 中常用的 loop 有如下三
* for
* while
* until
for loop 是从一个清单列表中读进变量值,并"依次"的循环执行 do 到 done 之间的命令行。
for var in one two three four five
do
echo -----------
echo '$var is '$var
echo
done
上例的执行结果将会是:
1) for 会定义一个叫 var 的变量,其值依次是 one two three four five 。
2) 因为有 5 个变量值,因此 do 与 done 之间的命令行会被循环执行 5 次。
3) 每次循环均用 echo 产生三行句子。
而第二行中不在 hard quote 之内的 $var 会依次被替换为 one two three four
five 。
4) 当最后一个变量值处理完毕,循环结束。
for ((i=1;i<=10;i++))
do
echo "num is $i"
done
除了 for loop ,上面的例子我们也可改用 while loop 来做到:
num=1
while [ "$num" -le 10 ]; do
echo "num is $num"
num=$(($num + 1))
done
while loop 的原理与 for loop 稍有不同:
它不是逐次处理清单中的变量值,而是取决于 while 后面的命令行之 return value :
* 若为 ture ,则执行 do 与 done 之间的命令,然后重新判断 while 后的 return value 。
* 若为 false ,则不再执行 do 与 done 之间的命令而结束循环。
分析上例:
1) 在 while 之前,定义变量 num=1 。
2) 然后测试(test) $num 是否小于或等于 10 。
3) 结果为 true ,于是执行 echo 并将 num 的值加一。
4) 再作第二轮测试,其时 num 的值为 1+1=2 ,依然小于或等于 10,因此为
true ,继续循环。
5) 直到 num 为 10+1=11 时,测试才会失败... 于是结束循环。
* 若 while 的测试结果永远为 true 的话,那循环将一直永久执行下去:
* 与 while 相反,until 是在 return value 为 false 时进入循环,否则结束。
因此,前面的例子我们也可以轻松的用 until 来写:
num=1
until [ ! "$num" -le 10 ]; do
echo "num is $num
num=$(($num + 1))
done
或是:
代码:
num=1
until [ "$num" -gt 10 ]; do
echo "num is $num"
num=$(($num + 1))
done
转载于:https://blog.51cto.com/qqtthappygo/955792
最后
以上就是风趣世界为你收集整理的细读shell-4的全部内容,希望文章能够帮你解决细读shell-4所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复