⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process-sub.html

📁 Shall高级编程
💻 HTML
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><HTML><HEAD><TITLE>Process Substitution</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="Advanced Topics"HREF="part5.html"><LINKREL="PREVIOUS"TITLE="Restricted Shells"HREF="restricted-sh.html"><LINKREL="NEXT"TITLE="Functions"HREF="functions.html"><METAHTTP-EQUIV="Content-Style-Type"CONTENT="text/css"><LINKREL="stylesheet"HREF="common/kde-common.css"TYPE="text/css"><METAHTTP-EQUIV="Content-Type"CONTENT="text/html; charset=iso-8859-1"><METAHTTP-EQUIV="Content-Language"CONTENT="en"><LINKREL="stylesheet"HREF="common/kde-localised.css"TYPE="text/css"TITLE="KDE-English"><LINKREL="stylesheet"HREF="common/kde-default.css"TYPE="text/css"TITLE="KDE-Default"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#AA0000"VLINK="#AA0055"ALINK="#AA0000"STYLE="font-family: sans-serif;"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="restricted-sh.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="functions.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="PROCESS-SUB"></A>Chapter 22. Process Substitution</H1><P><ANAME="PROCESSSUBREF"></A><AHREF="special-chars.html#PIPEREF">Piping</A> the <TTCLASS="FILENAME">stdout</TT>	of a command into the <TTCLASS="FILENAME">stdin</TT> of another	is a powerful technique.  But, what if you need to pipe the	<TTCLASS="FILENAME">stdout</TT> of <SPANCLASS="emphasis"><ICLASS="EMPHASIS">multiple</I></SPAN>	commands? This is where <TTCLASS="REPLACEABLE"><I>process	substitution</I></TT> comes in.</P><P><ICLASS="FIRSTTERM">Process substitution</I> feeds the        output of a process (or processes) into the        <TTCLASS="FILENAME">stdin</TT> of another process.</P><DIVCLASS="VARIABLELIST"><P><B><ANAME="COMMANDSPARENS1"></A>Template</B></P><DL><DT>Command list enclosed within parentheses</DT><DD><P><BCLASS="COMMAND">&#62;(command_list)</B></P><P><BCLASS="COMMAND">&#60;(command_list)</B></P><P>Process substitution uses	    <TTCLASS="FILENAME">/dev/fd/&#60;n&#62;</TT> files to send the	    results of the process(es) within parentheses to another process.	      <ANAME="AEN16838"HREF="#FTN.AEN16838">[1]</A>	  </P><DIVCLASS="CAUTION"><TABLECLASS="CAUTION"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/caution.png"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>There is <SPANCLASS="emphasis"><ICLASS="EMPHASIS">no</I></SPAN> space between the            the <SPANCLASS="QUOTE">"&#60;"</SPAN> or <SPANCLASS="QUOTE">"&#62;"</SPAN> and the parentheses.            Space there would give an error message.</P></TD></TR></TABLE></DIV></DD></DL></DIV><P>	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>echo &#62;(true)</B></TT> <TTCLASS="COMPUTEROUTPUT">/dev/fd/63</TT>  <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>echo &#60;(true)</B></TT> <TTCLASS="COMPUTEROUTPUT">/dev/fd/63</TT> 	      </PRE></TD></TR></TABLE>	  Bash creates a pipe with two <AHREF="io-redirection.html#FDREF">file	  descriptors</A>, <TTCLASS="FILENAME">--fIn</TT> and	  <TTCLASS="FILENAME">fOut--</TT>.	The <TTCLASS="FILENAME">stdin</TT>	  of <AHREF="internal.html#TRUEREF">true</A> connects	  to <TTCLASS="FILENAME">fOut</TT> (dup2(fOut, 0)),	  then Bash passes a <TTCLASS="FILENAME">/dev/fd/fIn</TT>	  argument to <BCLASS="COMMAND">echo</B>. On systems lacking	  <TTCLASS="FILENAME">/dev/fd/&#60;n&#62;</TT> files, Bash may use	  temporary files. (Thanks, S.C.)</P><P>Process substitution can compare the output of two	       different commands, or even the output of different options	       to the same command.</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>comm &#60;(ls -l) &#60;(ls -al)</B></TT> <TTCLASS="COMPUTEROUTPUT">total 12-rw-rw-r--    1 bozo bozo       78 Mar 10 12:58 File0-rw-rw-r--    1 bozo bozo       42 Mar 10 12:58 File2-rw-rw-r--    1 bozo bozo      103 Mar 10 12:58 t2.sh        total 20        drwxrwxrwx    2 bozo bozo     4096 Mar 10 18:10 .        drwx------   72 bozo bozo     4096 Mar 10 17:58 ..        -rw-rw-r--    1 bozo bozo       78 Mar 10 12:58 File0        -rw-rw-r--    1 bozo bozo       42 Mar 10 12:58 File2        -rw-rw-r--    1 bozo bozo      103 Mar 10 12:58 t2.sh</TT></PRE></TD></TR></TABLE><P><ANAME="PCC2DIR"></A></P><P>	        Using process substitution to compare the contents		of two directories (to see which filenames are in one,		but not the other):		<TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;diff &#60;(ls $first_directory) &#60;(ls $second_directory)</PRE></TD></TR></TABLE>              </P><P>Some other usages and uses of process substitution:</P><P><ANAME="PSFDSTDIN"></A></P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;read -a list &#60; &#60;( od -Ad -w24 -t u2 /dev/urandom )   2&nbsp;#  Read a list of random numbers from /dev/urandom,   3&nbsp;#+ process with "od"   4&nbsp;#+ and feed into stdin of "read" . . .   5&nbsp;   6&nbsp;#  From "insertion-sort.bash" example script.   7&nbsp;#  Courtesy of JuanJo Ciarlante.</PRE></TD></TR></TABLE></P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;cat &#60;(ls -l)   2&nbsp;# Same as     ls -l | cat   3&nbsp;   4&nbsp;sort -k 9 &#60;(ls -l /bin) &#60;(ls -l /usr/bin) &#60;(ls -l /usr/X11R6/bin)   5&nbsp;# Lists all the files in the 3 main 'bin' directories, and sorts by filename.   6&nbsp;# Note that three (count 'em) distinct commands are fed to 'sort'.   7&nbsp;   8&nbsp;    9&nbsp;diff &#60;(command1) &#60;(command2)    # Gives difference in command output.  10&nbsp;  11&nbsp;tar cf &#62;(bzip2 -c &#62; file.tar.bz2) $directory_name  12&nbsp;# Calls "tar cf /dev/fd/?? $directory_name", and "bzip2 -c &#62; file.tar.bz2".  13&nbsp;#  14&nbsp;# Because of the /dev/fd/&#60;n&#62; system feature,  15&nbsp;# the pipe between both commands does not need to be named.  16&nbsp;#  17&nbsp;# This can be emulated.  18&nbsp;#  19&nbsp;bzip2 -c &#60; pipe &#62; file.tar.bz2&#38;  20&nbsp;tar cf pipe $directory_name  21&nbsp;rm pipe  22&nbsp;#        or  23&nbsp;exec 3&#62;&#38;1  24&nbsp;tar cf /dev/fd/4 $directory_name 4&#62;&#38;1 &#62;&#38;3 3&#62;&#38;- | bzip2 -c &#62; file.tar.bz2 3&#62;&#38;-  25&nbsp;exec 3&#62;&#38;-  26&nbsp;  27&nbsp;  28&nbsp;# Thanks, St閜hane Chazelas</PRE></TD></TR></TABLE></P><P>A reader sent in the following interesting example of process        substitution.</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;# Script fragment taken from SuSE distribution:   2&nbsp;   3&nbsp;# --------------------------------------------------------------#   4&nbsp;while read  des what mask iface; do   5&nbsp;# Some commands ...   6&nbsp;done &#60; &#60;(route -n)     7&nbsp;#    ^ ^  First &#60; is redirection, second is process substitution.   8&nbsp;   9&nbsp;# To test it, let's make it do something.  10&nbsp;while read  des what mask iface; do  11&nbsp;  echo $des $what $mask $iface  12&nbsp;done &#60; &#60;(route -n)    13&nbsp;  14&nbsp;# Output:  15&nbsp;# Kernel IP routing table  16&nbsp;# Destination Gateway Genmask Flags Metric Ref Use Iface  17&nbsp;# 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo  18&nbsp;# --------------------------------------------------------------#  19&nbsp;  20&nbsp;#  As St閜hane Chazelas points out,  21&nbsp;#+ an easier-to-understand equivalent is:  22&nbsp;route -n |  23&nbsp;  while read des what mask iface; do   # Variables set from output of pipe.  24&nbsp;    echo $des $what $mask $iface  25&nbsp;  done  #  This yields the same output as above.  26&nbsp;        #  However, as Ulrich Gayer points out . . .  27&nbsp;        #+ this simplified equivalent uses a subshell for the while loop,  28&nbsp;        #+ and therefore the variables disappear when the pipe terminates.  29&nbsp;	  30&nbsp;# --------------------------------------------------------------#  31&nbsp;	  32&nbsp;#  However, Filip Moritz comments that there is a subtle difference  33&nbsp;#+ between the above two examples, as the following shows.  34&nbsp;  35&nbsp;(  36&nbsp;route -n | while read x; do ((y++)); done  37&nbsp;echo $y # $y is still unset  38&nbsp;  39&nbsp;while read x; do ((y++)); done &#60; &#60;(route -n)  40&nbsp;echo $y # $y has the number of lines of output of route -n  41&nbsp;)  42&nbsp;  43&nbsp;More generally spoken  44&nbsp;(  45&nbsp;: | x=x  46&nbsp;# seems to start a subshell like  47&nbsp;: | ( x=x )  48&nbsp;# while  49&nbsp;x=x &#60; &#60;(:)  50&nbsp;# does not  51&nbsp;)  52&nbsp;  53&nbsp;# This is useful, when parsing csv and the like.  54&nbsp;# That is, in effect, what the original SuSE code fragment does.</PRE></TD></TR></TABLE></P></DIV><H3CLASS="FOOTNOTES">Notes</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN16838"HREF="process-sub.html#AEN16838">[1]</A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>This has the same effect as a		<AHREF="extmisc.html#NAMEDPIPEREF">named pipe</A> (temp		file), and, in fact, named pipes were at one time used		in process substitution.</P></TD></TR></TABLE><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="restricted-sh.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="functions.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Restricted Shells</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part5.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Functions</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

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