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

📄 arrays.html

📁 BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版
💻 HTML
📖 第 1 页 / 共 5 页
字号:
 10&nbsp;#  依此类推.  11&nbsp;#  这意味着每轮比较不需要比较之前已经"沉淀"好的数据.  12&nbsp;#  因此你会注意到后边的数据在打印的时候会快一些.  13&nbsp; 14&nbsp; 15&nbsp;exchange() 16&nbsp;{ 17&nbsp;  # 交换数组中的两个元素.  18&nbsp;  local temp=${Countries[$1]} #  临时保存 19&nbsp;                              #+ 要交换的那个元素.  20&nbsp;  Countries[$1]=${Countries[$2]} 21&nbsp;  Countries[$2]=$temp 22&nbsp;   23&nbsp;  return 24&nbsp;}   25&nbsp; 26&nbsp;declare -a Countries  #  声明数组,  27&nbsp;                      #+ 此处是可选的, 因为数组在下面被初始化.  28&nbsp; 29&nbsp;#  我们是否可以使用转义符(\) 30&nbsp;#+ 来将数组元素的值放在不同的行上?  31&nbsp;#  可以.  32&nbsp; 33&nbsp;Countries=(Netherlands Ukraine Zaire Turkey Russia Yemen Syria \ 34&nbsp;Brazil Argentina Nicaragua Japan Mexico Venezuela Greece England \ 35&nbsp;Israel Peru Canada Oman Denmark Wales France Kenya \ 36&nbsp;Xanadu Qatar Liechtenstein Hungary) 37&nbsp; 38&nbsp;# "Xanadu"虚拟出来的世外桃源.  39&nbsp;#+  40&nbsp; 41&nbsp; 42&nbsp;clear                      # 开始之前的清屏动作.  43&nbsp; 44&nbsp;echo "0: ${Countries[*]}"  # 从索引0开始列出整个数组.  45&nbsp; 46&nbsp;number_of_elements=${#Countries[@]} 47&nbsp;let "comparisons = $number_of_elements - 1" 48&nbsp; 49&nbsp;count=1 # 传递数字.  50&nbsp; 51&nbsp;while [ "$comparisons" -gt 0 ]          # 开始外部循环 52&nbsp;do 53&nbsp; 54&nbsp;  index=0  # 在每轮循环开始之前, 重置索引.  55&nbsp; 56&nbsp;  while [ "$index" -lt "$comparisons" ] # 开始内部循环 57&nbsp;  do 58&nbsp;    if [ ${Countries[$index]} \&#62; ${Countries[`expr $index + 1`]} ] 59&nbsp;    #  如果原来的排序次序不对... 60&nbsp;    #  回想一下, 在单括号中,  61&nbsp;    #+ \&#62;是ASCII码的比较操作符.  62&nbsp; 63&nbsp;    #  if [[ ${Countries[$index]} &#62; ${Countries[`expr $index + 1`]} ]] 64&nbsp;    #+ 这样也行.  65&nbsp;    then 66&nbsp;      exchange $index `expr $index + 1`  # 交换.  67&nbsp;    fi   68&nbsp;    let "index += 1"  # 或者,   index+=1   在Bash 3.1之后的版本才能这么用.  69&nbsp;  done # 内部循环结束 70&nbsp; 71&nbsp;# ---------------------------------------------------------------------- 72&nbsp;# Paulo Marcel Coelho Aragao建议我们可以使用更简单的for循环.  73&nbsp;# 74&nbsp;# for (( last = $number_of_elements - 1 ; last &#62; 1 ; last-- )) 75&nbsp;# do 76&nbsp;#     for (( i = 0 ; i &#60; last ; i++ )) 77&nbsp;#     do 78&nbsp;#         [[ "${Countries[$i]}" &#62; "${Countries[$((i+1))]}" ]] \ 79&nbsp;#             &#38;&#38; exchange $i $((i+1)) 80&nbsp;#     done 81&nbsp;# done 82&nbsp;# ---------------------------------------------------------------------- 83&nbsp;   84&nbsp; 85&nbsp;let "comparisons -= 1" #  因为最"重"的元素到了底部,  86&nbsp;                       #+ 所以每轮我们可以少做一次比较.  87&nbsp; 88&nbsp;echo 89&nbsp;echo "$count: ${Countries[@]}"  # 每轮结束后, 都打印一次数组.  90&nbsp;echo 91&nbsp;let "count += 1"                # 增加传递计数.  92&nbsp; 93&nbsp;done                            # 外部循环结束 94&nbsp;                                # 至此, 全部完成.  95&nbsp; 96&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>--</P><P>我们可以在数组中嵌套数组么? </P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# "嵌套"数组.   3&nbsp;  4&nbsp;#  Michael Zick提供了这个用例,   5&nbsp;#+ William Park做了一些修正和说明.   6&nbsp;  7&nbsp;AnArray=( $(ls --inode --ignore-backups --almost-all \  8&nbsp;	--directory --full-time --color=none --time=status \  9&nbsp;	--sort=time -l ${PWD} ) )  # 命令及选项.  10&nbsp; 11&nbsp;# 空格是有意义的 . . . 并且不要在上边用引号引用任何东西.  12&nbsp; 13&nbsp;SubArray=( ${AnArray[@]:11:1}  ${AnArray[@]:6:5} ) 14&nbsp;#  这个数组有六个元素:  15&nbsp;#+     SubArray=( [0]=${AnArray[11]} [1]=${AnArray[6]} [2]=${AnArray[7]} 16&nbsp;#      [3]=${AnArray[8]} [4]=${AnArray[9]} [5]=${AnArray[10]} ) 17&nbsp;# 18&nbsp;#  Bash数组是字符串(char *)类型 19&nbsp;#+ 的(循环)链表.  20&nbsp;#  因此, 这不是真正意义上的嵌套数组,  21&nbsp;#+ 只不过功能很相似而已.  22&nbsp; 23&nbsp;echo "Current directory and date of last status change:" 24&nbsp;echo "${SubArray[@]}" 25&nbsp; 26&nbsp;exit 0</PRE></FONT></TD></TR></TABLE></P><P>--</P><P>如果将<SPANCLASS="QUOTE">"嵌套数组"</SPAN>与<AHREF="bashver2.html#VARREFNEW">间接引用</A>组合起来使用的话, 		 将会产生一些非常有趣的用法. 	</P><DIVCLASS="EXAMPLE"><HR><ANAME="EMBARR"></A><P><B>例子 26-12. 嵌套数组与间接引用</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# embedded-arrays.sh  3&nbsp;# 嵌套数组和间接引用.   4&nbsp;  5&nbsp;# 本脚本由Dennis Leeuw编写.   6&nbsp;# 经过授权, 在本书中使用.   7&nbsp;# 本书作者做了少许修改.   8&nbsp;  9&nbsp; 10&nbsp;ARRAY1=( 11&nbsp;        VAR1_1=value11 12&nbsp;        VAR1_2=value12 13&nbsp;        VAR1_3=value13 14&nbsp;) 15&nbsp; 16&nbsp;ARRAY2=( 17&nbsp;        VARIABLE="test" 18&nbsp;        STRING="VAR1=value1 VAR2=value2 VAR3=value3" 19&nbsp;        ARRAY21=${ARRAY1[*]} 20&nbsp;)       # 将ARRAY1嵌套到这个数组中.  21&nbsp; 22&nbsp;function print () { 23&nbsp;        OLD_IFS="$IFS" 24&nbsp;        IFS=$'\n'       #  这么做是为了每行 25&nbsp;                        #+ 只打印一个数组元素. 26&nbsp;        TEST1="ARRAY2[*]" 27&nbsp;        local ${!TEST1} # 删除这一行, 看看会发生什么?  28&nbsp;        #  间接引用.  29&nbsp;	#  这使得$TEST1 30&nbsp;	#+ 只能够在函数内被访问.  31&nbsp; 32&nbsp; 33&nbsp;        #  让我们看看还能干点什么.  34&nbsp;        echo 35&nbsp;        echo "\$TEST1 = $TEST1"       #  仅仅是变量名字.  36&nbsp;        echo; echo 37&nbsp;        echo "{\$TEST1} = ${!TEST1}"  #  变量内容.  38&nbsp;                                      #  这就是 39&nbsp;                                      #+ 间接引用的作用.  40&nbsp;        echo 41&nbsp;        echo "-------------------------------------------"; echo 42&nbsp;        echo 43&nbsp; 44&nbsp; 45&nbsp;        # 打印变量 46&nbsp;        echo "Variable VARIABLE: $VARIABLE" 47&nbsp;	 48&nbsp;        # 打印一个字符串元素 49&nbsp;        IFS="$OLD_IFS" 50&nbsp;        TEST2="STRING[*]" 51&nbsp;        local ${!TEST2}      # 间接引用(同上).  52&nbsp;        echo "String element VAR2: $VAR2 from STRING" 53&nbsp; 54&nbsp;        # 打印一个数组元素 55&nbsp;        TEST2="ARRAY21[*]" 56&nbsp;        local ${!TEST2}      # 间接引用(同上).  57&nbsp;        echo "Array element VAR1_1: $VAR1_1 from ARRAY21" 58&nbsp;} 59&nbsp; 60&nbsp;print 61&nbsp;echo 62&nbsp; 63&nbsp;exit 0 64&nbsp; 65&nbsp;#   脚本作者注,  66&nbsp;#+ "你可以很容易的将其扩展成一个能创建hash的Bash脚本."  67&nbsp;#   (难) 留给读者的练习: 实现它. </PRE></FONT></TD></TR></TABLE><HR></DIV><P>--</P><P>数组使得<EM>埃拉托色尼素数筛子</EM>有了shell版本的实现. 		  当然, 如果你需要的是追求效率的应用, 那么就应该使用编译行语言来实现, 		  比如C语言. 因为脚本运行的太慢了. 	</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX68"></A><P><B>例子 26-13. 复杂的数组应用:              <EM>埃拉托色尼素数筛子</EM></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# sieve.sh (ex68.sh)  3&nbsp;  4&nbsp;# 埃拉托色尼素数筛子  5&nbsp;# 找素数的经典算法.   6&nbsp;  7&nbsp;#  在同等数值的范围内,   8&nbsp;#+ 这个脚本运行的速度比C版本慢的多.   9&nbsp; 10&nbsp;LOWER_LIMIT=1       # 从1开始.  11&nbsp;UPPER_LIMIT=1000    # 到1000.  12&nbsp;# (如果你时间很多的话 . . . 你可以将这个数值调的很高.) 13&nbsp; 14&nbsp;PRIME=1 15&nbsp;NON_PRIME=0 16&nbsp; 17&nbsp;let SPLIT=UPPER_LIMIT/2 18&nbsp;# 优化:  19&nbsp;# 只需要测试中间到最大的值(为什么?).  20&nbsp;# (译者注: 这个变量在脚本正文并没有被使用, 仅仅在107行之后的优化部分才使用.) 21&nbsp; 22&nbsp;declare -a Primes 23&nbsp;# Primes[]是个数组.  24&nbsp; 25&nbsp; 26&nbsp;initialize () 27&nbsp;{ 28&nbsp;# 初始化数组.  29&nbsp; 30&nbsp;i=$LOWER_LIMIT 31&nbsp;until [ "$i" -gt "$UPPER_LIMIT" ] 32&nbsp;do 33&nbsp;  Primes[i]=$PRIME 34&nbsp;  let "i += 1" 35&nbsp;done 36&nbsp;#  假定所有数组成员都是需要检查的(素数) 37&nbsp;#+ 直到检查完成.  38&nbsp;} 39&nbsp; 40&nbsp;print_primes () 41&nbsp;{ 42&nbsp;# 打印出所有数组Primes[]中被标记为素数的元素.  43&nbsp; 44&nbsp;i=$LOWER_LIMIT 45&nbsp; 46&nbsp;until [ "$i" -gt "$UPPER_LIMIT" ] 47&nbsp;do 48&nbsp; 49&nbsp;  if [ "${Primes[i]}" -eq "$PRIME" ] 50&nbsp;  then 51&nbsp;    printf "%8d" $i 52&nbsp;    # 每个数字打印前先打印8个空格, 在偶数列才打印.  53&nbsp;  fi 54&nbsp;   55&nbsp;  let "i += 1" 56&nbsp;   57&nbsp;done 58&nbsp; 59&nbsp;} 60&nbsp; 61&nbsp;sift () # 查出非素数.  62&nbsp;{ 63&nbsp; 64&nbsp;let i=$LOWER_LIMIT+1 65&nbsp;# 我们都知道1是素数, 所以我们从2开始.  66&nbsp;# (译者注: 从2开始并不是由于1是素数, 而是因为要去掉以后每个数的倍数, 感谢网友KevinChen.) 67&nbsp;until [ "$i" -gt "$UPPER_LIMIT" ] 68&nbsp;do 69&nbsp; 70&nbsp;if [ "${Primes[i]}" -eq "$PRIME" ] 71&nbsp;# 不要处理已经过滤过的数字(被标识为非素数). 72&nbsp;then 73&nbsp; 74&nbsp;  t=$i 75&nbsp; 76&nbsp;  while [ "$t" -le "$UPPER_LIMIT" ] 77&nbsp;  do 78&nbsp;    let "t += $i " 79&nbsp;    Primes[t]=$NON_PRIME 80&nbsp;    # 标识为非素数.  81&nbsp;  done 82&nbsp; 83&nbsp;fi   84&nbsp; 85&nbsp;  let "i += 1" 86&nbsp;done   87&nbsp; 88&nbsp; 89&nbsp;} 90&nbsp; 91&nbsp; 92&nbsp;# ============================================== 93&nbsp;# main () 94&nbsp;# 继续调用函数.  95&nbsp;initialize 96&nbsp;sift 97&nbsp;print_primes 98&nbsp;# 这里就是被称为结构化编程的东西.  99&nbsp;# ==============================================100&nbsp;101&nbsp;echo102&nbsp;103&nbsp;exit 0104&nbsp;105&nbsp;106&nbsp;107&nbsp;# -------------------------------------------------------- #108&nbsp;# 因为前面的'exit'语句, 所以后边的代码不会运行. 109&nbsp;110&nbsp;#  下边的代码, 是由Stephane Chazelas所编写的埃拉托色尼素数筛子的改进版本, 111&nbsp;#+ 这个版本可以运行的快一些. 112&nbsp;113&nbsp;# 必须在命令行上指定参数(这个参数就是: 寻找素数的限制范围). 114&nbsp;115&nbsp;UPPER_LIMIT=$1                  # 来自于命令行. 116&nbsp;let SPLIT=UPPER_LIMIT/2         # 从中间值到最大值. 117&nbsp;118&nbsp;Primes=( '' $(seq $UPPER_LIMIT) )119&nbsp;120&nbsp;i=1121&nbsp;until (( ( i += 1 ) &#62; SPLIT ))  # 仅需要从中间值检查. 122&nbsp;do123&nbsp;  if [[ -n $Primes[i] ]]124&nbsp;  then125&nbsp;    t=$i126&nbsp;    until (( ( t += i ) &#62; UPPER_LIMIT ))127&nbsp;    do128&nbsp;      Primes[t]=129&nbsp;    done130&nbsp;  fi  131&nbsp;done  132&nbsp;echo ${Primes[*]}133&nbsp;134&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>上边的这个例子是基于数组的素数产生器, 		  还有不使用数组的素数产生器<AHREF="contributed-scripts.html#PRIMES">例子 A-16</A>, 		让我们来比较一番. </P><P>--</P><P>数组可以进行一定程度上的扩展, 		  这样就可以模拟一些Bash原本不支持的数据结构.         </P><DIVCLASS="EXAMPLE"><HR><ANAME="STACKEX"></A><P><B>例子 26-14. 模拟一个下推堆栈</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# stack.sh: 模拟下推堆栈  3&nbsp;  4&nbsp;#  类似于CPU栈, 下推堆栈依次保存数据项,   5&nbsp;#+ 但是取数据时, 却反序进行, 后进先出.   6&nbsp;  7&nbsp;BP=100            #  栈数组的基址指针.   8&nbsp;                  #  从元素100开始.   9&nbsp; 10&nbsp;SP=$BP            #  栈指针.  11&nbsp;                  #  将其初始化为栈"基址"(栈底).  12&nbsp; 13&nbsp;Data=             #  当前栈的数据内容.  14&nbsp;                  #  必须定义为全局变量,  15&nbsp;                  #+ 因为函数所能够返回的整数存在范围限制.  16&nbsp; 17&nbsp;declare -a stack 18&nbsp; 19&nbsp; 20&nbsp;push()            # 压栈. 21&nbsp;{

⌨️ 快捷键说明

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