mofdan 发表于 2018-8-24 12:01:13

细读shell-4

  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 &quot;Do you want to continue? (Yes/No): &quot;
  read YN
  if [ &quot;$YN&quot; = Y -o &quot;$YN&quot; = y -o &quot;$YN&quot; = &quot;Yes&quot; -o &quot;$YN&quot; = &quot;yes&quot; -o &quot;$YN&quot; = &quot;YES&quot; ]
  then
  QQ
  else
  exit 0
  fi
  }
  QQ
  从例中,我们看得出来,最麻烦的部份是在于判断 YN 的值可能有好几种式样。
  ..
  if echo &quot;$YN&quot; | grep -q '^\(\)*$'
  
  
  QQ () {
  echo -n &quot;Do you want to continue? (Yes/No): &quot;
  read YN
  case &quot;$YN&quot; in
  |)
  QQ
  ;;
  *)
  
  exit 0
  ;;
  esac
  }
  QQ
  我们常 case 的判断式来判断某一变量在同的值(通常是 string)时作出不同的处理,
  比方说,判断 script 参数以执行不同的命令。
  若你有兴趣、且用 Linux 系统的话,不妨挖一挖 /etc/init.d/* 里那堆 script 中的 case 用
  法。
  case &quot;$1&quot; in
  start)
  start
  ;;
  stop)
  stop
  ;;
  status)
  rhstatus
  ;;
  restart|reload)
  restart
  ;;
  condrestart)
  [ -f /var/lock/subsys/syslog ] && restart || :
  ;;
  *)
  echo $&quot;Usage: $0 {start|stop|status|restart|condrestart}&quot;
  exit 1
  esac
  18.最后要介绍的是 shell script 设计中常见的&quot;循环&quot;(loop)。
  bash shell 中常用的 loop 有如下三
  * for
  * while
  * until
  for loop 是从一个清单列表中读进变量值,并&quot;依次&quot;的循环执行 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
页: [1]
查看完整版本: 细读shell-4