📄 internal.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><HTML><HEAD><TITLE>Internal Commands and Builtins</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="Commands"HREF="part4.html"><LINKREL="PREVIOUS"TITLE="Commands"HREF="part4.html"><LINKREL="NEXT"TITLE="External Filters, Programs and Commands"HREF="external.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="part4.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="external.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="INTERNAL"></A>Chapter 14. Internal Commands and Builtins</H1><P><ANAME="BUILTINREF"></A>A <ICLASS="FIRSTTERM">builtin</I> is a <BCLASS="COMMAND">command</B> contained within the Bash tool set, literally <ICLASS="FIRSTTERM">built in</I>. This is either for performance reasons -- builtins execute faster than external commands, which usually require <ICLASS="FIRSTTERM">forking off</I> a separate process -- or because a particular builtin needs direct access to the shell internals.</P><P><ANAME="FORKREF"></A></P><TABLECLASS="SIDEBAR"BORDER="1"CELLPADDING="5"><TR><TD><DIVCLASS="SIDEBAR"><ANAME="AEN7770"></A><P>When a command or the shell itself initiates (or <ICLASS="FIRSTTERM">spawns</I>) a new subprocess to carry out a task, this is called <ICLASS="FIRSTTERM">forking</I>. This new process is the <ICLASS="FIRSTTERM">child</I>, and the process that <ICLASS="FIRSTTERM">forked</I> it off is the <ICLASS="FIRSTTERM">parent</I>. While the <ICLASS="FIRSTTERM">child process</I> is doing its work, the <ICLASS="FIRSTTERM">parent process</I> is still executing.</P><P>Note that while a <ICLASS="FIRSTTERM">parent process</I> gets the <ICLASS="FIRSTTERM">process ID</I> of the <ICLASS="FIRSTTERM">child process</I>, and can thus pass arguments to it, <SPANCLASS="emphasis"><ICLASS="EMPHASIS">the reverse is not true</I></SPAN>. <AHREF="gotchas.html#PARCHILDPROBREF">This can create problems that are subtle and hard to track down.</A></P><DIVCLASS="EXAMPLE"><HR><ANAME="SPAWNSCR"></A><P><B>Example 14-1. A script that forks off multiple instances of itself</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # spawn.sh 3 4 5 PIDS=$(pidof sh $0) # Process IDs of the various instances of this script. 6 P_array=( $PIDS ) # Put them in an array (why?). 7 echo $PIDS # Show process IDs of parent and child processes. 8 let "instances = ${#P_array[*]} - 1" # Count elements, less 1. 9 # Why subtract 1? 10 echo "$instances instance(s) of this script running." 11 echo "[Hit Ctl-C to exit.]"; echo 12 13 14 sleep 1 # Wait. 15 sh $0 # Play it again, Sam. 16 17 exit 0 # Not necessary; script will never get to here. 18 # Why not? 19 20 # After exiting with a Ctl-C, 21 #+ do all the spawned instances of the script die? 22 # If so, why? 23 24 # Note: 25 # ---- 26 # Be careful not to run this script too long. 27 # It will eventually eat up too many system resources. 28 29 # Is having a script spawn multiple instances of itself 30 #+ an advisable scripting technique. 31 # Why or why not?</PRE></TD></TR></TABLE><HR></DIV><P><ANAME="BLTINFRK"></A></P><P>Generally, a Bash <ICLASS="FIRSTTERM">builtin</I> does not fork a subprocess when it executes within a script. An external system command or filter in a script usually <SPANCLASS="emphasis"><ICLASS="EMPHASIS">will</I></SPAN> fork a subprocess.</P></DIV></TD></TR></TABLE><P>A builtin may be a synonym to a system command of the same name, but Bash reimplements it internally. For example, the Bash <BCLASS="COMMAND">echo</B> command is not the same as <TTCLASS="FILENAME">/bin/echo</TT>, although their behavior is almost identical. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 echo "This line uses the \"echo\" builtin." 4 /bin/echo "This line uses the /bin/echo system command."</PRE></TD></TR></TABLE> </P><P><ANAME="KEYWORDREF"></A>A <ICLASS="FIRSTTERM">keyword</I> is a <ICLASS="FIRSTTERM">reserved</I> word, token or operator. Keywords have a special meaning to the shell, and indeed are the building blocks of the shell's syntax. As examples, <SPANCLASS="QUOTE">"<SPANCLASS="TOKEN">for</SPAN>"</SPAN>, <SPANCLASS="QUOTE">"<SPANCLASS="TOKEN">while</SPAN>"</SPAN>, <SPANCLASS="QUOTE">"do"</SPAN>, and <SPANCLASS="QUOTE">"<SPANCLASS="TOKEN">!</SPAN>"</SPAN> are keywords. Similar to a <AHREF="internal.html#BUILTINREF">builtin</A>, a keyword is hard-coded into Bash, but unlike a <ICLASS="FIRSTTERM">builtin</I>, a keyword is not in itself a command, but <SPANCLASS="emphasis"><ICLASS="EMPHASIS">a subunit of a larger command structure</I></SPAN>. <ANAME="AEN7811"HREF="#FTN.AEN7811">[1]</A> </P><DIVCLASS="VARIABLELIST"><P><B><ANAME="INTIO1"></A>I/O</B></P><DL><DT><ANAME="ECHOREF"></A><BCLASS="COMMAND">echo</B></DT><DD><P>prints (to <TTCLASS="FILENAME">stdout</TT>) an expression or variable (see <AHREF="variables.html#EX9">Example 4-1</A>). <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 echo Hello 2 echo $a</PRE></TD></TR></TABLE></P><P>An <BCLASS="COMMAND">echo</B> requires the <TTCLASS="OPTION">-e</TT> option to print escaped characters. See <AHREF="escapingsection.html#ESCAPED">Example 5-2</A>.</P><P>Normally, each <BCLASS="COMMAND">echo</B> command prints a terminal newline, but the <TTCLASS="OPTION">-n</TT> option suppresses this.</P><P><ANAME="ECHOGREPREF"></A></P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>An <BCLASS="COMMAND">echo</B> can be used to feed a sequence of commands down a pipe.</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 if echo "$VAR" | grep -q txt # if [[ $VAR = *txt* ]] 2 then 3 echo "$VAR contains the substring sequence \"txt\"" 4 fi</PRE></TD></TR></TABLE></P></TD></TR></TABLE></DIV><P><ANAME="ECHOCS"></A></P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>An <BCLASS="COMMAND">echo</B>, in combination with <AHREF="commandsub.html#COMMANDSUBREF">command substitution</A> can set a variable.</P><P><TTCLASS="USERINPUT"><B>a=`echo "HELLO" | tr A-Z a-z`</B></TT></P><P>See also <AHREF="textproc.html#LOWERCASE">Example 15-21</A>, <AHREF="moreadv.html#EX57">Example 15-3</A>, <AHREF="mathc.html#MONTHLYPMT">Example 15-45</A>, and <AHREF="mathc.html#BASE">Example 15-46</A>.</P></TD></TR></TABLE></DIV><P>Be aware that <BCLASS="COMMAND">echo `command`</B> deletes any linefeeds that the output of <TTCLASS="REPLACEABLE"><I>command</I></TT> generates.</P><P>The <AHREF="variables2.html#IFSREF">$IFS</A> (internal field separator) variable normally contains <SPANCLASS="TOKEN">\n</SPAN> (linefeed) as one of its set of <AHREF="special-chars.html#WHITESPACEREF">whitespace</A> characters. Bash therefore splits the output of <TTCLASS="REPLACEABLE"><I>command</I></TT> at linefeeds into arguments to <BCLASS="COMMAND">echo</B>. Then <BCLASS="COMMAND">echo</B> outputs these arguments, separated by spaces.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>ls -l /usr/share/apps/kjezz/sounds</B></TT> <TTCLASS="COMPUTEROUTPUT">-rw-r--r-- 1 root root 1407 Nov 7 2000 reflect.au -rw-r--r-- 1 root root 362 Nov 7 2000 seconds.au</TT> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>echo `ls -l /usr/share/apps/kjezz/sounds`</B></TT> <TTCLASS="COMPUTEROUTPUT">total 40 -rw-r--r-- 1 root root 716 Nov 7 2000 reflect.au -rw-r--r-- 1 root root ...</TT> </PRE></TD></TR></TABLE> </P><P> So, how can we embed a linefeed within an <AHREF="internal.html#ECHOREF">echoed</A> character string? <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 # Embedding a linefeed? 2 echo "Why doesn't this string \n split on two lines?" 3 # Doesn't split. 4 5 # Let's try something else. 6 7 echo 8 9 echo $"A line of text containing 10 a linefeed." 11 # Prints as two distinct lines (embedded linefeed). 12 # But, is the "$" variable prefix really necessary? 13 14 echo 15 16 echo "This string splits 17 on two lines." 18 # No, the "$" is not needed. 19 20 echo 21 echo "---------------" 22 echo 23 24 echo -n $"Another line of text containing 25 a linefeed." 26 # Prints as two distinct lines (embedded linefeed). 27 # Even the -n option fails to suppress the linefeed here. 28 29 echo 30 echo 31 echo "---------------" 32 echo 33 echo 34 35 # However, the following doesn't work as expected. 36 # Why not? Hint: Assignment to a variable. 37 string1=$"Yet another line of text containing 38 a linefeed (maybe)." 39 40 echo $string1 41 # Yet another line of text containing a linefeed (maybe). 42 # ^ 43 # Linefeed becomes a space. 44 45 # Thanks, Steve Parker, for pointing this out.</PRE></TD></TR></TABLE> </P><P><ANAME="BINECHO"></A></P><DIVCLASS="NOTE"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -