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

📄 loops.html

📁 一本完整的描述Unix Shell 编程的工具书的所有范例
💻 HTML
📖 第 1 页 / 共 3 页
字号:
CLASS="USERINPUT"><B>in [list]</B></TT> part of a	      <ICLASS="FIRSTTERM">for loop</I> causes the loop to operate	      on <SPANCLASS="TOKEN">$@</SPAN> -- the list of arguments given	      on the command line to the script. A particularly clever	      illustration of this is <AHREF="contributed-scripts.html#PRIMES">Example A-16</A>.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX23"></A><P><B>Example 10-5. Missing <TTCLASS="USERINPUT"><B>in [list]</B></TT> in a		<BCLASS="COMMAND">for</B> loop</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;   3&nbsp;#  Invoke this script both with and without arguments,   4&nbsp;#+ and see what happens.   5&nbsp;   6&nbsp;for a   7&nbsp;do   8&nbsp; echo -n "$a "   9&nbsp;done  10&nbsp;  11&nbsp;#  The 'in list' missing, therefore the loop operates on '$@'  12&nbsp;#+ (command-line argument list, including whitespace).  13&nbsp;  14&nbsp;echo  15&nbsp;  16&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>It is possible to use <AHREF="commandsub.html#COMMANDSUBREF">command substitution</A>	      to generate the <TTCLASS="USERINPUT"><B>[list]</B></TT> in a	      <ICLASS="FIRSTTERM">for loop</I>. See also <AHREF="extmisc.html#EX53">Example 12-49</A>,	      <AHREF="loops.html#SYMLINKS">Example 10-10</A> and <AHREF="mathc.html#BASE">Example 12-43</A>.</P><DIVCLASS="EXAMPLE"><HR><ANAME="FORLOOPCMD"></A><P><B>Example 10-6. Generating the [list] in a <BCLASS="COMMAND">for</B>	        loop with command substitution</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;#  for-loopcmd.sh: for-loop with [list]   3&nbsp;#+ generated by command substitution.   4&nbsp;   5&nbsp;NUMBERS="9 7 3 8 37.53"   6&nbsp;   7&nbsp;for number in `echo $NUMBERS`  # for number in 9 7 3 8 37.53   8&nbsp;do   9&nbsp;  echo -n "$number "  10&nbsp;done  11&nbsp;  12&nbsp;echo   13&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>Here is a somewhat more complex example of using command	      substitution to create the [list].</P><DIVCLASS="EXAMPLE"><HR><ANAME="BINGREP"></A><P><B>Example 10-7. A <AHREF="textproc.html#GREPREF">grep</A> replacement	        for binary files</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# bin-grep.sh: Locates matching strings in a binary file.   3&nbsp;   4&nbsp;# A "grep" replacement for binary files.   5&nbsp;# Similar effect to "grep -a"   6&nbsp;   7&nbsp;E_BADARGS=65   8&nbsp;E_NOFILE=66   9&nbsp;  10&nbsp;if [ $# -ne 2 ]  11&nbsp;then  12&nbsp;  echo "Usage: `basename $0` search_string filename"  13&nbsp;  exit $E_BADARGS  14&nbsp;fi  15&nbsp;  16&nbsp;if [ ! -f "$2" ]  17&nbsp;then  18&nbsp;  echo "File \"$2\" does not exist."  19&nbsp;  exit $E_NOFILE  20&nbsp;fi    21&nbsp;  22&nbsp;  23&nbsp;IFS=$'\012'       # Per suggestion of Anton Filippov.  24&nbsp;                  # was:  IFS="\n"  25&nbsp;for word in $( strings "$2" | grep "$1" )  26&nbsp;# The "strings" command lists strings in binary files.  27&nbsp;# Output then piped to "grep", which tests for desired string.  28&nbsp;do  29&nbsp;  echo $word  30&nbsp;done  31&nbsp;  32&nbsp;# As S.C. points out, lines 23 - 30 could be replaced with the simpler  33&nbsp;#    strings "$2" | grep "$1" | tr -s "$IFS" '[\n*]'  34&nbsp;  35&nbsp;  36&nbsp;# Try something like  "./bin-grep.sh mem /bin/ls"  to exercise this script.  37&nbsp;  38&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>More of the same.</P><DIVCLASS="EXAMPLE"><HR><ANAME="USERLIST"></A><P><B>Example 10-8. Listing all users on the system</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# userlist.sh   3&nbsp;   4&nbsp;PASSWORD_FILE=/etc/passwd   5&nbsp;n=1           # User number   6&nbsp;   7&nbsp;for name in $(awk 'BEGIN{FS=":"}{print $1}' &#60; "$PASSWORD_FILE" )   8&nbsp;# Field separator = :    ^^^^^^   9&nbsp;# Print first field              ^^^^^^^^  10&nbsp;# Get input from password file               ^^^^^^^^^^^^^^^^^  11&nbsp;do  12&nbsp;  echo "USER #$n = $name"  13&nbsp;  let "n += 1"  14&nbsp;done    15&nbsp;  16&nbsp;  17&nbsp;# USER #1 = root  18&nbsp;# USER #2 = bin  19&nbsp;# USER #3 = daemon  20&nbsp;# ...  21&nbsp;# USER #30 = bozo  22&nbsp;  23&nbsp;exit 0  24&nbsp;  25&nbsp;#  Exercise:  26&nbsp;#  --------  27&nbsp;#  How is it that an ordinary user (or a script run by same)  28&nbsp;#+ can read /etc/passwd?  29&nbsp;#  Isn't this a security hole? Why or why not?</PRE></TD></TR></TABLE><HR></DIV><P>A final example of the [list] resulting from command	      substitution.</P><DIVCLASS="EXAMPLE"><HR><ANAME="FINDSTRING"></A><P><B>Example 10-9. Checking all the binaries in a directory for	      authorship</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# findstring.sh:   3&nbsp;# Find a particular string in binaries in a specified directory.   4&nbsp;   5&nbsp;directory=/usr/bin/   6&nbsp;fstring="Free Software Foundation"  # See which files come from the FSF.   7&nbsp;   8&nbsp;for file in $( find $directory -type f -name '*' | sort )   9&nbsp;do  10&nbsp;  strings -f $file | grep "$fstring" | sed -e "s%$directory%%"  11&nbsp;  #  In the "sed" expression,  12&nbsp;  #+ it is necessary to substitute for the normal "/" delimiter  13&nbsp;  #+ because "/" happens to be one of the characters filtered out.  14&nbsp;  #  Failure to do so gives an error message (try it).  15&nbsp;done    16&nbsp;  17&nbsp;exit 0  18&nbsp;  19&nbsp;#  Exercise (easy):  20&nbsp;#  ---------------  21&nbsp;#  Convert this script to taking command-line parameters  22&nbsp;#+ for $directory and $fstring.</PRE></TD></TR></TABLE><HR></DIV><P>The output of a <ICLASS="FIRSTTERM">for loop</I> may be piped to	      a command or commands.</P><DIVCLASS="EXAMPLE"><HR><ANAME="SYMLINKS"></A><P><B>Example 10-10. Listing the <AHREF="external.html#SYMLINKREF">symbolic	        links</A> in a directory</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# symlinks.sh: Lists symbolic links in a directory.   3&nbsp;   4&nbsp;   5&nbsp;directory=${1-`pwd`}   6&nbsp;#  Defaults to current working directory,   7&nbsp;#+ if not otherwise specified.   8&nbsp;#  Equivalent to code block below.   9&nbsp;# ----------------------------------------------------------  10&nbsp;# ARGS=1                 # Expect one command-line argument.  11&nbsp;#  12&nbsp;# if [ $# -ne "$ARGS" ]  # If not 1 arg...  13&nbsp;# then  14&nbsp;#   directory=`pwd`      # current working directory  15&nbsp;# else  16&nbsp;#   directory=$1  17&nbsp;# fi  18&nbsp;# ----------------------------------------------------------  19&nbsp;  20&nbsp;echo "symbolic links in directory \"$directory\""  21&nbsp;  22&nbsp;for file in "$( find $directory -type l )"   # -type l = symbolic links  23&nbsp;do  24&nbsp;  echo "$file"  25&nbsp;done | sort                                  # Otherwise file list is unsorted.  26&nbsp;#  Strictly speaking, a loop isn't really necessary here,  27&nbsp;#+ since the output of the "find" command is expanded into a single word.  28&nbsp;#  However, it's easy to understand and illustrative this way.  29&nbsp;  30&nbsp;#  As Dominik 'Aeneas' Schnitzer points out,  31&nbsp;#+ failing to quote  $( find $directory -type l )  32&nbsp;#+ will choke on filenames with embedded whitespace.  33&nbsp;#  Even this will only pick up the first field of each argument.  34&nbsp;  35&nbsp;exit 0  36&nbsp;  37&nbsp;  38&nbsp;# Jean Helou proposes the following alternative:  39&nbsp;  40&nbsp;echo "symbolic links in directory \"$directory\""  41&nbsp;# Backup of the current IFS. One can never be too cautious.  42&nbsp;OLDIFS=$IFS  43&nbsp;IFS=:  44&nbsp;  45&nbsp;for file in $(find $directory -type l -printf "%p$IFS")  46&nbsp;do     #                              ^^^^^^^^^^^^^^^^  47&nbsp;       echo "$file"  48&nbsp;       done|sort</PRE></TD></TR></TABLE><HR></DIV><P>The <TTCLASS="FILENAME">stdout</TT> of a loop may be <AHREF="io-redirection.html#IOREDIRREF">redirected</A> to a file, as this slight	      modification to the previous example shows.</P><DIVCLASS="EXAMPLE"><HR><ANAME="SYMLINKS2"></A><P><B>Example 10-11. Symbolic links in a directory, saved to a file</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# symlinks.sh: Lists symbolic links in a directory.   3&nbsp;   4&nbsp;OUTFILE=symlinks.list                         # save file   5&nbsp;   6&nbsp;directory=${1-`pwd`}   7&nbsp;#  Defaults to current working directory,   8&nbsp;#+ if not otherwise specified.   9&nbsp;  10&nbsp;  11&nbsp;echo "symbolic links in directory \"$directory\"" &#62; "$OUTFILE"  12&nbsp;echo "---------------------------" &#62;&#62; "$OUTFILE"  13&nbsp;  14&nbsp;for file in "$( find $directory -type l )"    # -type l = symbolic links  15&nbsp;do  16&nbsp;  echo "$file"  17&nbsp;done | sort &#62;&#62; "$OUTFILE"                     # stdout of loop  18&nbsp;#           ^^^^^^^^^^^^^                       redirected to save file.  19&nbsp;  20&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>There is an alternative syntax to a <ICLASS="FIRSTTERM">for	      loop</I> that will look very familiar to C	      programmers. This requires double parentheses.</P><DIVCLASS="EXAMPLE"><HR><ANAME="FORLOOPC"></A><P><B>Example 10-12. A C-like <BCLASS="COMMAND">for</B> loop</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# Two ways to count up to 10.   3&nbsp;   4&nbsp;echo   5&nbsp;   6&nbsp;# Standard syntax.   7&nbsp;for a in 1 2 3 4 5 6 7 8 9 10   8&nbsp;do   9&nbsp;  echo -n "$a "  10&nbsp;done    11&nbsp;  12&nbsp;echo; echo  13&nbsp;  14&nbsp;# +==========================================+  15&nbsp;  16&nbsp;# Now, let's do the same, using C-like syntax.  17&nbsp;  18&nbsp;LIMIT=10  19&nbsp;  20&nbsp;for ((a=1; a &#60;= LIMIT ; a++))  # Double parentheses, and "LIMIT" with no "$".  21&nbsp;do  22&nbsp;  echo -n "$a "  23&nbsp;done                           # A construct borrowed from 'ksh93'.  24&nbsp;  25&nbsp;echo; echo  26&nbsp;  27&nbsp;# +=========================================================================+  28&nbsp;  29&nbsp;# Let's use the C "comma operator" to increment two variables simultaneously.  30&nbsp;  31&nbsp;for ((a=1, b=1; a &#60;= LIMIT ; a++, b++))  # The comma chains together operations.  32&nbsp;do  33&nbsp;  echo -n "$a-$b "  34&nbsp;done  35&nbsp;  36&nbsp;echo; echo  37&nbsp;  38&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>See also <AHREF="arrays.html#QFUNCTION">Example 26-15</A>, <AHREF="arrays.html#TWODIM">Example 26-16</A>, and <AHREF="contributed-scripts.html#COLLATZ">Example A-6</A>.</P><P>---</P><P>Now, a <ICLASS="FIRSTTERM">for loop</I> used in a	      <SPANCLASS="QUOTE">"real-life"</SPAN> context.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX24"></A><P><B>Example 10-13. Using <BCLASS="COMMAND">efax</B> in batch mode</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# Faxing (must have 'fax' installed).   3&nbsp;   4&nbsp;EXPECTED_ARGS=2   5&nbsp;E_BADARGS=65   6&nbsp;

⌨️ 快捷键说明

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