📄 loopcontrol.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><HTML><HEAD><TITLE>Loop Control</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="Loops and Branches"HREF="loops.html"><LINKREL="PREVIOUS"TITLE="Nested Loops"HREF="nestedloops.html"><LINKREL="NEXT"TITLE="Testing and Branching"HREF="testbranch.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="SECT1"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="nestedloops.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 10. Loops and Branches</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="testbranch.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="LOOPCONTROL"></A>10.3. Loop Control</H1><DIVCLASS="VARIABLELIST"><P><B><ANAME="BRKCONT1"></A>Commands Affecting Loop Behavior</B></P><DL><DT><BCLASS="COMMAND">break</B>, <BCLASS="COMMAND">continue</B></DT><DD><P>The <BCLASS="COMMAND">break</B> and <BCLASS="COMMAND">continue</B> loop control commands <ANAME="AEN6203"HREF="#FTN.AEN6203">[1]</A> correspond exactly to their counterparts in other programming languages. The <BCLASS="COMMAND">break</B> command terminates the loop (breaks out of it), while <BCLASS="COMMAND">continue</B> causes a jump to the next <ICLASS="FIRSTTERM">iteration</I> (repetition) of the loop, skipping all the remaining commands in that particular loop cycle.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX28"></A><P><B>Example 10-20. Effects of <ICLASS="FIRSTTERM">break</I> and <BCLASS="COMMAND">continue</B> in a loop</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 LIMIT=19 # Upper limit 4 5 echo 6 echo "Printing Numbers 1 through 20 (but not 3 and 11)." 7 8 a=0 9 10 while [ $a -le "$LIMIT" ] 11 do 12 a=$(($a+1)) 13 14 if [ "$a" -eq 3 ] || [ "$a" -eq 11 ] # Excludes 3 and 11. 15 then 16 continue # Skip rest of this particular loop iteration. 17 fi 18 19 echo -n "$a " # This will not execute for 3 and 11. 20 done 21 22 # Exercise: 23 # Why does loop print up to 20? 24 25 echo; echo 26 27 echo Printing Numbers 1 through 20, but something happens after 2. 28 29 ################################################################## 30 31 # Same loop, but substituting 'break' for 'continue'. 32 33 a=0 34 35 while [ "$a" -le "$LIMIT" ] 36 do 37 a=$(($a+1)) 38 39 if [ "$a" -gt 2 ] 40 then 41 break # Skip entire rest of loop. 42 fi 43 44 echo -n "$a " 45 done 46 47 echo; echo; echo 48 49 exit 0</PRE></TD></TR></TABLE><HR></DIV><P><ANAME="BREAKPARAM"></A></P><P>The <BCLASS="COMMAND">break</B> command may optionally take a parameter. A plain <BCLASS="COMMAND">break</B> terminates only the innermost loop in which it is embedded, but a <BCLASS="COMMAND">break N</B> breaks out of <TTCLASS="PARAMETER"><I>N</I></TT> levels of loop.</P><DIVCLASS="EXAMPLE"><HR><ANAME="BREAKLEVELS"></A><P><B>Example 10-21. Breaking out of multiple loop levels</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # break-levels.sh: Breaking out of loops. 3 4 # "break N" breaks out of N level loops. 5 6 for outerloop in 1 2 3 4 5 7 do 8 echo -n "Group $outerloop: " 9 10 # -------------------------------------------------------- 11 for innerloop in 1 2 3 4 5 12 do 13 echo -n "$innerloop " 14 15 if [ "$innerloop" -eq 3 ] 16 then 17 break # Try break 2 to see what happens. 18 # ("Breaks" out of both inner and outer loops.) 19 fi 20 done 21 # -------------------------------------------------------- 22 23 echo 24 done 25 26 echo 27 28 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>The <BCLASS="COMMAND">continue</B> command, similar to <BCLASS="COMMAND">break</B>, optionally takes a parameter. A plain <BCLASS="COMMAND">continue</B> cuts short the current iteration within its loop and begins the next. A <BCLASS="COMMAND">continue N</B> terminates all remaining iterations at its loop level and continues with the next iteration at the loop, <TTCLASS="OPTION">N</TT> levels above.</P><DIVCLASS="EXAMPLE"><HR><ANAME="CONTINUELEVELS"></A><P><B>Example 10-22. Continuing at a higher loop level</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # The "continue N" command, continuing at the Nth level loop. 3 4 for outer in I II III IV V # outer loop 5 do 6 echo; echo -n "Group $outer: " 7 8 # -------------------------------------------------------------------- 9 for inner in 1 2 3 4 5 6 7 8 9 10 # inner loop 10 do 11 12 if [ "$inner" -eq 7 ] 13 then 14 continue 2 # Continue at loop on 2nd level, that is "outer loop". 15 # Replace above line with a simple "continue" 16 # to see normal loop behavior. 17 fi 18 19 echo -n "$inner " # 7 8 9 10 will never echo. 20 done 21 # -------------------------------------------------------------------- 22 23 done 24 25 echo; echo 26 27 # Exercise: 28 # Come up with a meaningful use for "continue N" in a script. 29 30 exit 0</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="CONTINUENEX"></A><P><B>Example 10-23. Using <ICLASS="FIRSTTERM">continue N</I> in an actual task</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 # Albert Reiner gives an example of how to use "continue N": 2 # --------------------------------------------------------- 3 4 # Suppose I have a large number of jobs that need to be run, with 5 #+ any data that is to be treated in files of a given name pattern in a 6 #+ directory. There are several machines that access this directory, and 7 #+ I want to distribute the work over these different boxen. Then I 8 #+ usually nohup something like the following on every box: 9 10 while true 11 do 12 for n in .iso.* 13 do 14 [ "$n" = ".iso.opts" ] && continue 15 beta=${n#.iso.} 16 [ -r .Iso.$beta ] && continue 17 [ -r .lock.$beta ] && sleep 10 && continue 18 lockfile -r0 .lock.$beta || continue 19 echo -n "$beta: " `date` 20 run-isotherm $beta 21 date 22 ls -alF .Iso.$beta 23 [ -r .Iso.$beta ] && rm -f .lock.$beta 24 continue 2 25 done 26 break 27 done 28 29 # The details, in particular the sleep N, are particular to my 30 #+ application, but the general pattern is: 31 32 while true 33 do 34 for job in {pattern} 35 do 36 {job already done or running} && continue 37 {mark job as running, do job, mark job as done} 38 continue 2 39 done 40 break # Or something like `sleep 600' to avoid termination. 41 done 42 43 # This way the script will stop only when there are no more jobs to do 44 #+ (including jobs that were added during runtime). Through the use 45 #+ of appropriate lockfiles it can be run on several machines 46 #+ concurrently without duplication of calculations [which run a couple 47 #+ of hours in my case, so I really want to avoid this]. Also, as search 48 #+ always starts again from the beginning, one can encode priorities in 49 #+ the file names. Of course, one could also do this without `continue 2', 50 #+ but then one would have to actually check whether or not some job 51 #+ was done (so that we should immediately look for the next job) or not 52 #+ (in which case we terminate or sleep for a long time before checking 53 #+ for a new job).</PRE></TD></TR></TABLE><HR></DIV><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>The <BCLASS="COMMAND">continue N</B> construct is difficult to understand and tricky to use in any meaningful context. It is probably best avoided.</P></TD></TR></TABLE></DIV></DD></DL></DIV></DIV><H3CLASS="FOOTNOTES">Notes</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN6203"HREF="loopcontrol.html#AEN6203">[1]</A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>These are shell <AHREF="internal.html#BUILTINREF">builtins</A>, whereas other loop commands, such as <AHREF="loops.html#WHILELOOPREF">while</A> and <AHREF="testbranch.html#CASEESAC1">case</A>, are <AHREF="internal.html#KEYWORDREF">keywords</A>.</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="nestedloops.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="testbranch.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Nested Loops</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="loops.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Testing and Branching</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -