📄 arrays.html
字号:
ALIGN="LEFT"VALIGN="TOP"><P><BCLASS="COMMAND">array=( element1 element2 ... elementN )</B>初始化操作, 如果有<AHREF="commandsub.html#COMMANDSUBREF">命令替换</A>的帮助, 就可以将一个文本文件的内容加载到数组. </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 filename=sample_file 4 5 # cat sample_file 6 # 7 # 1 a b c 8 # 2 d e fg 9 10 11 declare -a array1 12 13 array1=( `cat "$filename"`) # 将$filename的内容 14 # List file to stdout #+ 加载到数组array1. 15 # 16 # array1=( `cat "$filename" | tr '\n' ' '`) 17 # 把文件中的换行替换为空格. 18 # 其实这么做是没必要的, Not necessary because Bash does word splitting, 19 #+ 因为Bash在做单词分割(word splitting)的时候, 将会把换行转换为空格. 20 21 echo ${array1[@]} # 打印数组. 22 # 1 a b c 2 d e fg 23 # 24 # 文件中每个被空白符分隔的"单词" 25 #+ 都被保存到数组的一个元素中. 26 27 element_count=${#array1[*]} 28 echo $element_count # 8</PRE></FONT></TD></TR></TABLE> </P></TD></TR></TABLE></DIV><P>出色的技巧使得数组的操作技术又多了一种. </P><DIVCLASS="EXAMPLE"><HR><ANAME="ARRAYASSIGN"></A><P><B>例子 26-8. 初始化数组</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #! /bin/bash 2 # array-assign.bash 3 4 # 数组操作是Bash所特有的, 5 #+ 所以才使用".bash"作为脚本扩展名. 6 7 # Copyright (c) Michael S. Zick, 2003, All rights reserved. 8 # License: Unrestricted reuse in any form, for any purpose. 9 # Version: $ID$ 10 # 11 # 说明与注释由William Park所添加. 12 13 # 基于Stephane Chazelas所提供的 14 #+ 出现在本书中的一个例子. 15 16 # 'times'命令的输出格式: 17 # User CPU <space> System CPU 18 # User CPU of dead children <space> System CPU of dead children 19 20 # Bash有两种方法, 21 #+ 可以将一个数组的所有元素都赋值给一个新的数组变量. 22 # 在2.04, 2.05a和2.05b版本的Bash中, 23 #+ 这两种方法都会丢弃数组中的"空引用"(null值)元素. 24 # 另一种给数组赋值的方法将会被添加到新版本的Bash中, 25 #+ 这种方法采用[subscript]=value形式, 来维护数组下标与元素值之间的关系. 26 27 # 可以使用内部命令来构造一个大数组, 28 #+ 当然, 构造一个包含上千元素数组的其他方法 29 #+ 也能很好的完成任务. 30 31 declare -a bigOne=( /dev/* ) 32 echo 33 echo 'Conditions: Unquoted, default IFS, All-Elements-Of' 34 echo "Number of elements in array is ${#bigOne[@]}" 35 36 # set -vx 37 38 39 40 echo 41 echo '- - testing: =( ${array[@]} ) - -' 42 times 43 declare -a bigTwo=( ${bigOne[@]} ) 44 # ^ ^ 45 times 46 47 echo 48 echo '- - testing: =${array[@]} - -' 49 times 50 declare -a bigThree=${bigOne[@]} 51 # 这次没用括号. 52 times 53 54 # 正如Stephane Chazelas所指出的, 通过比较, 55 #+ 可以了解到第二种格式的赋值比第三或第四种形式更快. 56 # 57 # William Park解释: 58 #+ 数组bigTwo是作为一个单个字符串被赋值的, 59 #+ 而数组bigThree, 则是一个元素一个元素进行的赋值. 60 # 所以, 实质上是: 61 # bigTwo=( [0]="... ... ..." ) 62 # bigThree=( [0]="..." [1]="..." [2]="..." ... ) 63 64 65 # 在本书的例子中, 我还是会继续使用第一种形式, 66 #+ 因为我认为这种形式更有利于将问题阐述清楚. 67 68 # 在我所使用的例子中, 在其中复用的部分, 69 #+ 还是使用了第二种形式, 那是因为这种形式更快. 70 71 # MSZ: 很抱歉早先的疏忽(译者: 应是指本书的老版本). 72 73 74 # 注意事项: 75 # --------- 76 # 31行和43行的"declare -a"语句其实不是必需的, 77 #+ 因为Array=( ... )形式 78 #+ 只能用于数组赋值. 79 # 然而, 如果省略这些声明的话, 80 #+ 会导致脚本后边的相关操作变慢. 81 # 试一下, 看看发生了什么. 82 83 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>在数组声明的时候添加一个额外的<BCLASS="COMMAND">declare -a</B>语句, 能够加速后续的数组操作速度. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="COPYARRAY"></A><P><B>例子 26-9. 拷贝和连接数组</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #! /bin/bash 2 # CopyArray.sh 3 # 4 # 这个脚本由Michael Zick所编写. 5 # 已通过作者授权, 可以在本书中使用. 6 7 # 如何"通过名字传值&通过名字返回"(译者注: 这里可以理解为C中的"数组指针", 或C++中的"数组引用") 8 #+ 或者"建立自己的赋值语句". 9 10 11 CpArray_Mac() { 12 13 # 建立赋值命令 14 15 echo -n 'eval ' 16 echo -n "$2" # 目的参数名 17 echo -n '=( ${' 18 echo -n "$1" # 原参数名 19 echo -n '[@]} )' 20 21 # 上边这些语句会构成一条命令. 22 # 这仅仅是形式上的问题. 23 } 24 25 declare -f CopyArray # 函数"指针" 26 CopyArray=CpArray_Mac # 构造语句 27 28 Hype() 29 { 30 31 # 需要连接的数组名为$1. 32 # (把这个数组与字符串"Really Rocks"结合起来, 形成一个新数组.) 33 # 并将结果从数组$2中返回. 34 35 local -a TMP 36 local -a hype=( Really Rocks ) 37 38 $($CopyArray $1 TMP) 39 TMP=( ${TMP[@]} ${hype[@]} ) 40 $($CopyArray TMP $2) 41 } 42 43 declare -a before=( Advanced Bash Scripting ) 44 declare -a after 45 46 echo "Array Before = ${before[@]}" 47 48 Hype before after 49 50 echo "Array After = ${after[@]}" 51 52 # 连接的太多了? 53 54 echo "What ${after[@]:3:2}?" 55 56 declare -a modest=( ${after[@]:2:1} ${after[@]:3:2} ) 57 # ---- 子串提取 ---- 58 59 echo "Array Modest = ${modest[@]}" 60 61 # 'before'发生了什么变化么? 62 63 echo "Array Before = ${before[@]}" 64 65 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="ARRAYAPPEND"></A><P><B>例子 26-10. 关于串联数组的更多信息</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #! /bin/bash 2 # array-append.bash 3 4 # Copyright (c) Michael S. Zick, 2003, All rights reserved. 5 # License: Unrestricted reuse in any form, for any purpose. 6 # Version: $ID$ 7 # 8 # 在格式上, 由M.C做了一些修改. 9 10 11 # 数组操作是Bash特有的属性. 12 # 传统的UNIX /bin/sh缺乏类似的功能. 13 14 15 # 将这个脚本的输出通过管道传递给'more', 16 #+ 这么做的目的是防止输出的内容超过终端能够显示的范围. 17 18 19 # 依次使用下标. 20 declare -a array1=( zero1 one1 two1 ) 21 # 数组中存在空缺的元素([1]未定义). 22 declare -a array2=( [0]=zero2 [2]=two2 [3]=three2 ) 23 24 echo 25 echo '- Confirm that the array is really subscript sparse. -' 26 echo "Number of elements: 4" # 仅仅为了演示, 所以就写死了. 27 for (( i = 0 ; i < 4 ; i++ )) 28 do 29 echo "Element [$i]: ${array2[$i]}" 30 done 31 # 也可以参考一个更通用的例子, basics-reviewed.bash. 32 33 34 declare -a dest 35 36 # 将两个数组合并(附加)到第3个数组. 37 echo 38 echo 'Conditions: Unquoted, default IFS, All-Elements-Of operator' 39 echo '- Undefined elements not present, subscripts not maintained. -' 40 # # 那些未定义的元素不会出现; 组合时会丢弃这些元素. 41 42 dest=( ${array1[@]} ${array2[@]} ) 43 # dest=${array1[@]}${array2[@]} # 令人奇怪的结果, 或许是个bug. 44 45 # 现在, 打印结果. 46 echo 47 echo '- - Testing Array Append - -' 48 cnt=${#dest[@]} 49 50 echo "Number of elements: $cnt" 51 for (( i = 0 ; i < cnt ; i++ )) 52 do 53 echo "Element [$i]: ${dest[$i]}" 54 done 55 56 # 将数组赋值给一个数组中的元素(两次). 57 dest[0]=${array1[@]} 58 dest[1]=${array2[@]} 59 60 # 打印结果. 61 echo 62 echo '- - Testing modified array - -' 63 cnt=${#dest[@]} 64 65 echo "Number of elements: $cnt" 66 for (( i = 0 ; i < cnt ; i++ )) 67 do 68 echo "Element [$i]: ${dest[$i]}" 69 done 70 71 # 检查第二个元素的修改状况. 72 echo 73 echo '- - Reassign and list second element - -' 74 75 declare -a subArray=${dest[1]} 76 cnt=${#subArray[@]} 77 78 echo "Number of elements: $cnt" 79 for (( i = 0 ; i < cnt ; i++ )) 80 do 81 echo "Element [$i]: ${subArray[$i]}" 82 done 83 84 # 如果你使用'=${ ... }'形式 85 #+ 将一个数组赋值到另一个数组的一个元素中, 86 #+ 那么这个数组的所有元素都会被转换为一个字符串, 87 #+ 这个字符串中的每个数组元素都以空格进行分隔(其实是IFS的第一个字符). 88 89 # 如果原来数组中的所有元素都不包含空白符 . . . 90 # 如果原来的数组下标都是连续的 . . . 91 # 那么我们就可以将原来的数组进行恢复. 92 93 # 从修改过的第二个元素中, 将原来的数组恢复出来. 94 echo 95 echo '- - Listing restored element - -' 96 97 declare -a subArray=( ${dest[1]} ) 98 cnt=${#subArray[@]} 99 100 echo "Number of elements: $cnt"101 for (( i = 0 ; i < cnt ; i++ ))102 do103 echo "Element [$i]: ${subArray[$i]}"104 done105 echo '- - Do not depend on this behavior. - -'106 echo '- - This behavior is subject to change - -'107 echo '- - in versions of Bash newer than version 2.05b - -'108 109 # MSZ: 抱歉, 之前混淆了一些要点(译者注: 指的是本书以前的版本). 110 111 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>--</P><P>有了数组, 我们就可以在脚本中实现一些比较熟悉的算法. 这么做, 到底是不是一个好主意, 我们在这里不做讨论, 还是留给读者决定吧. </P><DIVCLASS="EXAMPLE"><HR><ANAME="BUBBLE"></A><P><B>例子 26-11. 一位老朋友: <EM>冒泡排序</EM></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # bubble.sh: 一种排序方式, 冒泡排序. 3 4 # 回忆一下冒泡排序的算法. 我们在这里要实现它... 5 6 # 依靠连续的比较数组元素进行排序, 7 #+ 比较两个相邻元素, 如果顺序不对, 就交换这两个元素的位置. 8 # 当第一轮比较结束之后, 最"重"的元素就会被移动到最底部. 9 # 当第二轮比较结束之后, 第二"重"的元素就会被移动到次底部的位置.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -