📄 internal.html
字号:
7 # (Double quotes and spaces make it more readable.) 8 echo "11 + 5 = $a" # 16 9 10 let "a <<= 3" # Equivalent to let "a = a << 3" 11 echo "\"\$a\" (=16) left-shifted 3 places = $a" 12 # 128 13 14 let "a /= 4" # Equivalent to let "a = a / 4" 15 echo "128 / 4 = $a" # 32 16 17 let "a -= 5" # Equivalent to let "a = a - 5" 18 echo "32 - 5 = $a" # 27 19 20 let "a *= 10" # Equivalent to let "a = a * 10" 21 echo "27 * 10 = $a" # 270 22 23 let "a %= 8" # Equivalent to let "a = a % 8" 24 echo "270 modulo 8 = $a (270 / 8 = 33, remainder $a)" 25 # 6 26 27 echo 28 29 exit 0</PRE></TD></TR></TABLE><HR></DIV></DD><DT><ANAME="EVALREF"></A><BCLASS="COMMAND">eval</B></DT><DD><P><TTCLASS="USERINPUT"><B>eval arg1 [arg2] ... [argN]</B></TT></P><P>Combines the arguments in an expression or list of expressions and <ICLASS="FIRSTTERM">evaluates</I> them. Any variables contained within the expression are expanded. The result translates into a command. This can be useful for code generation from the command line or within a script.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>process=xterm</B></TT> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>show_process="eval ps ax | grep $process"</B></TT> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>$show_process</B></TT> <TTCLASS="COMPUTEROUTPUT">1867 tty1 S 0:02 xterm 2779 tty1 S 0:00 xterm 2886 pts/1 S 0:00 grep xterm</TT> </PRE></TD></TR></TABLE> </P><P><ANAME="EVALFORCED"></A></P><P>Each invocation of <ICLASS="FIRSTTERM">eval</I> forces a re-<SPANCLASS="emphasis"><ICLASS="EMPHASIS">evaluation</I></SPAN> of its arguments. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 a='$b' 2 b='$c' 3 c=d 4 5 echo $a # $b 6 # First level. 7 eval echo $a # $c 8 # Second level. 9 eval eval echo $a # d 10 # Third level. 11 12 # Thank you, E. Choroba.</PRE></TD></TR></TABLE></P><P><ANAME="EVALEFF"></A></P><DIVCLASS="EXAMPLE"><HR><ANAME="EX43"></A><P><B>Example 14-11. Showing the effect of <ICLASS="FIRSTTERM">eval</I></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # Exercising "eval" ... 3 4 y=`eval ls -l` # Similar to y=`ls -l` 5 echo $y #+ but linefeeds removed because "echoed" variable is unquoted. 6 echo 7 echo "$y" # Linefeeds preserved when variable is quoted. 8 9 echo; echo 10 11 y=`eval df` # Similar to y=`df` 12 echo $y #+ but linefeeds removed. 13 14 # When LF's not preserved, it may make it easier to parse output, 15 #+ using utilities such as "awk". 16 17 echo 18 echo "===========================================================" 19 echo 20 21 22 # Now, showing how to do something useful with "eval" . . . 23 # (Thank you, E. Choroba!) 24 25 version=3.4 # Can we split the version into major and minor 26 #+ part in one command? 27 echo "version = $version" 28 eval major=${version/./;minor=} # Replaces '.' in version by ';minor=' 29 # The substitution yields '3; minor=4' 30 #+ so eval does minor=4, major=3 31 echo Major: $major, minor: $minor # Major: 3, minor: 4</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="ECHOPARAMS"></A><P><B>Example 14-12. <ICLASS="FIRSTTERM">Echoing</I> the <ICLASS="FIRSTTERM">command-line parameters</I></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # echo-params.sh 3 4 # Call this script with a few command line parameters. 5 # For example: 6 # sh echo-params.sh first second third fourth fifth 7 8 params=$# # Number of command-line parameters. 9 param=1 # Start at first command-line param. 10 11 while [ "$param" -le "$params" ] 12 do 13 echo -n "Command line parameter " 14 echo -n \$$param # Gives only the *name* of variable. 15 # ^^^ # $1, $2, $3, etc. 16 # Why? 17 # \$ escapes the first "$" 18 #+ so it echoes literally, 19 #+ and $param dereferences "$param" . . . 20 #+ . . . as expected. 21 echo -n " = " 22 eval echo \$$param # Gives the *value* of variable. 23 # ^^^^ ^^^ # The "eval" forces the *evaluation* 24 #+ of \$$ 25 #+ as an indirect variable reference. 26 27 (( param ++ )) # On to the next. 28 done 29 30 exit $? 31 32 # ================================================= 33 34 $ sh echo-params.sh first second third fourth fifth 35 Command line parameter $1 = first 36 Command line parameter $2 = second 37 Command line parameter $3 = third 38 Command line parameter $4 = fourth 39 Command line parameter $5 = fifth</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX44"></A><P><B>Example 14-13. Forcing a log-off</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # Killing ppp to force a log-off. 3 4 # Script should be run as root user. 5 6 killppp="eval kill -9 `ps ax | awk '/ppp/ { print $1 }'`" 7 # -------- process ID of ppp ------- 8 9 $killppp # This variable is now a command. 10 11 12 # The following operations must be done as root user. 13 14 chmod 666 /dev/ttyS3 # Restore read+write permissions, or else what? 15 # Since doing a SIGKILL on ppp changed the permissions on the serial port, 16 #+ we restore permissions to previous state. 17 18 rm /var/lock/LCK..ttyS3 # Remove the serial port lock file. Why? 19 20 # Note: 21 # Depending on the hardware and even the kernel version, 22 #+ the modem port on your machine may be different -- 23 #+ /dev/ttyS1 or /dev/ttyS2. 24 25 exit 0 26 27 # Exercises: 28 # --------- 29 # 1) Have script check whether root user is invoking it. 30 # 2) Do a check on whether the process to be killed 31 #+ is actually running before attempting to kill it. 32 # 3) Write an alternate version of this script based on 'fuser': 33 #+ if [ fuser -s /dev/modem ]; then . . .</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="ROT14"></A><P><B>Example 14-14. A version of <ICLASS="FIRSTTERM">rot13</I></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # A version of "rot13" using 'eval'. 3 # Compare to "rot13.sh" example. 4 5 setvar_rot_13() # "rot13" scrambling 6 { 7 local varname=$1 varvalue=$2 8 eval $varname='$(echo "$varvalue" | tr a-z n-za-m)' 9 } 10 11 12 setvar_rot_13 var "foobar" # Run "foobar" through rot13. 13 echo $var # sbbone 14 15 setvar_rot_13 var "$var" # Run "sbbone" through rot13. 16 # Back to original variable. 17 echo $var # foobar 18 19 # This example by Stephane Chazelas. 20 # Modified by document author. 21 22 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>Rory Winston contributed the following instance of how useful <ICLASS="FIRSTTERM">eval</I> can be.</P><P><ANAME="EVALX0"></A></P><DIVCLASS="EXAMPLE"><HR><ANAME="EVALEX"></A><P><B>Example 14-15. Using <ICLASS="FIRSTTERM">eval</I> to force variable substitution in a <ICLASS="FIRSTTERM">Perl</I> script</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 In the Perl script "test.pl": 2 ... 3 my $WEBROOT = <WEBROOT_PATH>; 4 ... 5 6 To force variable substitution try: 7 $export WEBROOT_PATH=/usr/local/webroot 8 $sed 's/<WEBROOT_PATH>/$WEBROOT_PATH/' < test.pl > out 9 10 But this just gives: 11 my $WEBROOT = $WEBROOT_PATH; 12 13 However: 14 $export WEBROOT_PATH=/usr/local/webroot 15 $eval sed 's%\<WEBROOT_PATH\>%$WEBROOT_PATH%' < test.pl > out 16 # ==== 17 18 That works fine, and gives the expected substitution: 19 my $WEBROOT = /usr/local/webroot; 20 21 22 ### Correction applied to original example by Paulo Marcel Coelho Aragao.</PRE></TD></TR></TABLE><HR></DIV><P><ANAME="EVALRISK"></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>The <BCLASS="COMMAND">eval</B> command can be risky, and normally should be avoided when there exists a reasonable alternative. An <TTCLASS="USERINPUT"><B>eval $COMMANDS</B></TT> executes the contents of <TTCLASS="REPLACEABLE"><I>COMMANDS</I></TT>, which may contain such unpleasant surprises as <BCLASS="COMMAND">rm -rf *</B>. Running an <BCLASS="COMMAND">eval</B> on unfamiliar code written by persons unknown is living dangerously.</P></TD></TR></TABLE></DIV></DD><DT><ANAME="SETREF"></A><BCLASS="COMMAND">set</B></DT><DD><P>The <BCLASS="COMMAND">set</B> command changes the value of internal script variables/options. One use for this is to toggle <AHREF="options.html#OPTIONSREF">option flags</A> which help determine the behavior of the script. Another application for it is to reset the <AHREF="variables2.html#POSPARAMREF">positional parameters</A> that a script sees as the result of a command (<TTCLASS="USERINPUT"><B>set `command`</B></TT>). The script can then parse the fields of the command output.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX34"></A><P><B>Example 14-16. Using <ICLASS="FIRSTTERM">set</I> with positional parameters</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 # script "set-test" 4 5 # Invoke this script with three command line parameters, 6 # for example, "./set-test one two three". 7 8 echo 9 echo "Positional parameters before set \`uname -a\` :" 10 echo "Command-line argument #1 = $1" 11 echo "Command-line argument #2 = $2" 12 echo "Command-line argument #3 = $3" 13 14 15 set `uname -a` # Sets the positional parameters to the output 16 # of the command `uname -a` 17 18 echo $_ # unknown 19 # Flags set in script. 20 21 echo "Positional parameters after set \`uname -a\` :" 22 # $1, $2, $3, etc. reinitialized to result of `uname -a` 23 echo "Field #1 of 'uname -a' = $1" 24 echo "Field #2 of 'uname -a' = $2" 25 echo "Field #3 of 'uname -a' = $3" 26 echo --- 27 echo $_ # --- 28 echo 29 30 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>More fun with positional parameters.</P><DIVCLASS="EXAMPLE"><HR><ANAME="REVPOSPARAMS"></A><P><B>Example 14-17. Reversing the positional parameters</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # revposparams.sh: Reverse positional parameters. 3 # Script by Dan Jacobson, with stylistic revisions by document author. 4 5 6 set a\ b c d\ e; 7 # ^ ^ Spaces escaped 8 # ^ ^ Spaces not escaped 9 OIFS=$IFS; IFS=:; 10 # ^ Saving old IFS and setting new one. 11 12 echo 13 14 until [ $# -eq 0 ] 15 do # Step through positional parameters. 16 echo "### k0 = "$k"" # Before 17 k=$1:$k; # Append each pos param to loop variable. 18 # ^ 19 echo "### k = "$k"" # After 20 echo 21 shift; 22 done 23 24 set $k # Set new positional parameters. 25 echo - 26 echo $# # Count of positional parameters. 27 echo - 28 echo 29 30 for i # Omitting the "in list" sets the variable -- i -- 31 #+ to the positional parameters. 32 do 33 echo $i # Display new positional parameters. 34 done 35 36 IFS=$OIFS # Restore IFS. 37 38 # Question: 39 # Is it necessary to set an new IFS, internal field separator, 40 #+ in order for this script to work properly? 41 # What happens if you don't? Try it. 42 # And, why use the new IFS -- a colon -- in line 17, 43 #+ to append to the loop variable? 44 # What is the purpose of this? 45 46 exit 0 47 48 $ ./revposparams.sh 49 50 ### k0 = 51 ### k = a b 52 53 ### k0 = a b 54 ### k = c a b 55 56 ### k0 = c a b 57 ### k = d e c a b 58 59 - 60 3 61 - 62 63 d e 64 c 65 a b</PRE></TD></TR></TABLE><HR></DIV><P>Invoking <BCLASS="COMMAND">set</B> without any options or arguments simply lists all the <AHREF="othertypesv.html#ENVREF">environmental</A> and other variables that have been initialized.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="SCREEN"> <TTCLASS="PROMPT">bash$ </TT><TTCLASS="USERINPUT"><B>set</B></TT> <TTCLASS="COMPUTEROUTPUT">AUTHORCOPY=/home/bozo/posts BASH=/bin/bash
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -