欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

x13380.html

BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版
HTML
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>使用exec</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="UP"TITLE="I/O重定向"HREF="io-redirection.html"><LINKREL="PREVIOUS"TITLE="I/O重定向"HREF="io-redirection.html"><LINKREL="NEXT"TITLE="代码块重定向"HREF="redircb.html"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="io-redirection.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">16. I/O重定向</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="redircb.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="AEN13380">16.1. 使用<BCLASS="COMMAND">exec</B></A></H1><P><ANAME="USINGEXECREF"></A></P><P><BCLASS="COMMAND">exec &#60;filename</B>命令会将<TTCLASS="FILENAME">stdin</TT>重定向到文件中. 			从这句开始, 所有的<TTCLASS="FILENAME">stdin</TT>就都来自于这个文件了, 		而不是标准输入(通常都是键盘输入). 		这样就提供了一种按行读取文件的方法, 		并且可以使用<AHREF="sedawk.html#SEDREF">sed</A>和/或<AHREF="awk.html#AWKREF">awk</A>来对每一行进行分析. </P><DIVCLASS="EXAMPLE"><HR><ANAME="REDIR1"></A><P><B>例子 16-1. 使用<BCLASS="COMMAND">exec</B>重定向<TTCLASS="FILENAME">stdin</TT></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 使用'exec'重定向stdin.   3&nbsp;  4&nbsp;  5&nbsp;exec 6&#60;&#38;0          # 将文件描述符#6与stdin链接起来.   6&nbsp;                   # 保存stdin.   7&nbsp;  8&nbsp;exec &#60; data-file   # stdin被文件"data-file"所代替.   9&nbsp; 10&nbsp;read a1            # 读取文件"data-file"的第一行.  11&nbsp;read a2            # 读取文件"data-file"的第二行.  12&nbsp; 13&nbsp;echo 14&nbsp;echo "Following lines read from file." 15&nbsp;echo "-------------------------------" 16&nbsp;echo $a1 17&nbsp;echo $a2 18&nbsp; 19&nbsp;echo; echo; echo 20&nbsp; 21&nbsp;exec 0&#60;&#38;6 6&#60;&#38;- 22&nbsp;#  现在将stdin从fd #6中恢复, 因为刚才我们把stdin重定向到#6了,  23&nbsp;#+ 然后关闭fd #6 ( 6&#60;&#38;- ), 好让这个描述符继续被其他进程所使用.  24&nbsp;# 25&nbsp;# &#60;&#38;6 6&#60;&#38;-    这么做也可以.  26&nbsp; 27&nbsp;echo -n "Enter data  " 28&nbsp;read b1  # 现在"read"已经恢复正常了, 就是能够正常的从stdin中读取. 29&nbsp;echo "Input read from stdin." 30&nbsp;echo "----------------------" 31&nbsp;echo "b1 = $b1" 32&nbsp; 33&nbsp;echo 34&nbsp; 35&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>同样的, <BCLASS="COMMAND">exec &#62;filename</B>命令将会把<TTCLASS="FILENAME">stdout</TT>重定向到一个指定的文件中. 	  这样所有命令的输出就都会发送到那个指定的文件, 	  而不是<TTCLASS="FILENAME">stdout</TT>. </P><DIVCLASS="IMPORTANT"><P></P><TABLECLASS="IMPORTANT"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/important.gif"HSPACE="5"ALT="Important"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>			<BCLASS="COMMAND">exec N &#62; filename</B>会影响整个脚本或<EM>当前shell</EM>. 			对于这个指定<AHREF="special-chars.html#PROCESSIDREF">PID</A>的脚本或shell来说, 			从这句命令执行之后, 就会重定向到这个文件中, 			然而 . . .        </P><P>	  <BCLASS="COMMAND">N &#62; filename</B>只会影响新fork出来的进程, 而不会影响整个脚本或shell. 	  not the entire script or shell.        </P><P>感谢你, Ahmed Darwish, 指出这个问题. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="REASSIGNSTDOUT"></A><P><B>例子 16-2. 使用<BCLASS="COMMAND">exec</B>来重定向<TTCLASS="FILENAME">stdout</TT></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# reassign-stdout.sh  3&nbsp;  4&nbsp;LOGFILE=logfile.txt  5&nbsp;  6&nbsp;exec 6&#62;&#38;1           # 将fd #6与stdout链接起来.   7&nbsp;                    # 保存stdout.   8&nbsp;  9&nbsp;exec &#62; $LOGFILE     # stdout就被文件"logfile.txt"所代替了.  10&nbsp; 11&nbsp;# ----------------------------------------------------------- # 12&nbsp;# 在这块中所有命令的输出都会发送到文件$LOGFILE中.  13&nbsp; 14&nbsp;echo -n "Logfile: " 15&nbsp;date 16&nbsp;echo "-------------------------------------" 17&nbsp;echo 18&nbsp; 19&nbsp;echo "Output of \"ls -al\" command" 20&nbsp;echo 21&nbsp;ls -al 22&nbsp;echo; echo 23&nbsp;echo "Output of \"df\" command" 24&nbsp;echo 25&nbsp;df 26&nbsp; 27&nbsp;# ----------------------------------------------------------- # 28&nbsp; 29&nbsp;exec 1&#62;&#38;6 6&#62;&#38;-      # 恢复stdout, 然后关闭文件描述符#6.  30&nbsp; 31&nbsp;echo 32&nbsp;echo "== stdout now restored to default == " 33&nbsp;echo 34&nbsp;ls -al 35&nbsp;echo 36&nbsp; 37&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="UPPERCONV"></A><P><B>例子 16-3. 使用<BCLASS="COMMAND">exec</B>在同一个脚本中重定向<TTCLASS="FILENAME">stdin</TT>和<TTCLASS="FILENAME">stdout</TT></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# upperconv.sh  3&nbsp;# 将一个指定的输入文件转换为大写.   4&nbsp;  5&nbsp;E_FILE_ACCESS=70  6&nbsp;E_WRONG_ARGS=71  7&nbsp;  8&nbsp;if [ ! -r "$1" ]     # 判断指定的输入文件是否可读?   9&nbsp;then 10&nbsp;  echo "Can't read from input file!" 11&nbsp;  echo "Usage: $0 input-file output-file" 12&nbsp;  exit $E_FILE_ACCESS 13&nbsp;fi                   #  即使输入文件($1)没被指定 14&nbsp;                     #+ 也还是会以相同的错误退出(为什么?).  15&nbsp; 16&nbsp;if [ -z "$2" ] 17&nbsp;then 18&nbsp;  echo "Need to specify output file." 19&nbsp;  echo "Usage: $0 input-file output-file" 20&nbsp;  exit $E_WRONG_ARGS 21&nbsp;fi 22&nbsp; 23&nbsp; 24&nbsp;exec 4&#60;&#38;0 25&nbsp;exec &#60; $1            # 将会从输入文件中读取.  26&nbsp; 27&nbsp;exec 7&#62;&#38;1 28&nbsp;exec &#62; $2            # 将写到输出文件中.  29&nbsp;                     # 假设输出文件是可写的(添加检查?).  30&nbsp; 31&nbsp;# ----------------------------------------------- 32&nbsp;    cat - | tr a-z A-Z   # 转换为大写.  33&nbsp;#   ^^^^^                # 从stdin中读取.  34&nbsp;#           ^^^^^^^^^^   # 写到stdout上.  35&nbsp;# 然而, stdin和stdout都被重定向了.  36&nbsp;# ----------------------------------------------- 37&nbsp; 38&nbsp;exec 1&#62;&#38;7 7&#62;&#38;-       # 恢复stout. 39&nbsp;exec 0&#60;&#38;4 4&#60;&#38;-       # 恢复stdin. 40&nbsp; 41&nbsp;# 恢复之后, 下边这行代码将会如预期的一样打印到stdout上.  42&nbsp;echo "File \"$1\" written to \"$2\" as uppercase conversion." 43&nbsp; 44&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>I/O重定向是一种避免可怕的<AHREF="subshells.html#PARVIS">子shell中不可访问变量</A>问题的方法.       </P><DIVCLASS="EXAMPLE"><HR><ANAME="AVOIDSUBSHELL"></A><P><B>例子 16-4. 避免子shell</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# avoid-subshell.sh  3&nbsp;# 由Matthew Walker所提出的建议.   4&nbsp;  5&nbsp;Lines=0  6&nbsp;  7&nbsp;echo  8&nbsp;  9&nbsp;cat myfile.txt | while read line;  #  (译者注: 管道会产生子shell) 10&nbsp;                 do { 11&nbsp;                   echo $line 12&nbsp;                   (( Lines++ ));  #  增加这个变量的值 13&nbsp;                                   #+ 但是外部循环却不能访问.  14&nbsp;                                   #  子shell问题.  15&nbsp;                 } 16&nbsp;                 done 17&nbsp; 18&nbsp;echo "Number of lines read = $Lines"     # 0 19&nbsp;                                         # 错误! 20&nbsp; 21&nbsp;echo "------------------------" 22&nbsp; 23&nbsp; 24&nbsp;exec 3&#60;&#62; myfile.txt 25&nbsp;while read line &#60;&#38;3 26&nbsp;do { 27&nbsp;  echo "$line" 28&nbsp;  (( Lines++ ));                   #  增加这个变量的值 29&nbsp;                                   #+ 现在外部循环就可以访问了.  30&nbsp;                                   #  没有子shell, 现在就没问题了.  31&nbsp;} 32&nbsp;done 33&nbsp;exec 3&#62;&#38;- 34&nbsp; 35&nbsp;echo "Number of lines read = $Lines"     # 8 36&nbsp; 37&nbsp;echo 38&nbsp; 39&nbsp;exit 0 40&nbsp; 41&nbsp;# 下边这些行是这个脚本的结果, 脚本是不会走到这里的.  42&nbsp; 43&nbsp;$ cat myfile.txt 44&nbsp; 45&nbsp;Line 1. 46&nbsp;Line 2. 47&nbsp;Line 3. 48&nbsp;Line 4. 49&nbsp;Line 5. 50&nbsp;Line 6. 51&nbsp;Line 7. 52&nbsp;Line 8.</PRE></FONT></TD></TR></TABLE><HR></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="io-redirection.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">首页</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="redircb.html"ACCESSKEY="N">下一页</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">I/O重定向</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="io-redirection.html"ACCESSKEY="U">上一级</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">代码块重定向</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -