为感谢ChinaUnix上兄弟的无私帮助,我贡献一段关于shell数组的翻译,不足之处望大家海涵,海纳百川,有容乃大,希望大家尽己所能,发挥自由之精神。 (不知道刚才咋回事,发到Linux版了)
bash提供一维数组。使用一个数组前可以显式地以declare声明(言下之意,也可以不)。在数组元素的最大数目上并无约束,甚至,不要求数组元素被连续赋值。其下标从0开始。
一个数组可以通过如下赋值方式而自动创建:
name[subscript]=value
下标subscript必须为数,大于或等于0,显式声明如下:
declare -a name
为自己方便,也可写成
declare -a name[subscript],shell解释时忽略subscript.
用如下方式可对整个数组赋值
name=(value1 ... valuen)
其中value可用[subscript]=代替,从而具体指定对那个元素赋值。例子如下:
[shark@phi ver1.2]$ name=([0]=1 [2]=34 [3]=45)
[shark@phi ver1.2]$ echo ${name[0]}
1
[shark@phi ver1.2]$ echo ${name[1]}
[shark@phi ver1.2]$ echo ${name[2]}
34
[shark@phi ver1.2]$ echo ${name[3]}
45
[shark@phi ver1.2]$ echo ${name[4]}
[shark@phi ver1.2]$
(不过这样太不方便,个人意见,还不如按下标一个个写)
引用数组变量用
${name[subscript]}
必须用{},否则shell将有误解,而不予接受。
若下标为`@' or `*', 则做通配符解,代指所有数组元素。
[shark@phi ver1.2]$ echo ${name[*]}
1 34 45
[shark@phi ver1.2]$
[shark@phi ver1.2]$ echo ${name[@]}
1 34 45
但不可做赋值
name[*]=1 是错的。
数组元素可以是字符串。元素间以环境变量IFS的第一个字符分隔。
[shark@phi ver1.2]$ name=(hello glad to meet you)
[shark@phi ver1.2]$ echo ${name[0]}
hello
[shark@phi ver1.2]$ echo ${name[1]}
glad
[shark@phi ver1.2]$ echo ${name[2]}
to
[shark@phi ver1.2]$ echo ${name[3]}
meet
[shark@phi ver1.2]$ echo ${name[4]}
you
若要跨过分隔约束,用双引号括起
[shark@phi ver1.2]$ name=("hello glad" to meet you)
[shark@phi ver1.2]$ echo ${name[0]}
hello glad
[shark@phi ver1.2]$ echo ${name[1]}
to
[shark@phi ver1.2]$ echo ${name[2]}
meet
[shark@phi ver1.2]$ echo ${name[3]}
you
数组元素个数以${#name[subscript]} 计得
无下标的数组变量引用等价于引用其第零个元素。
用unset命令可以销毁一个数组
unset name 或者 unset name[*]
也可以只销毁一个元素
unset name[subscript]
read命令支持以 -a 参数从标准输入读入数组。
gzgzgz 回复于:2005-04-14 23:52:38
再灌一篇以供大家参考
#!/bin/bash
# array-ops.sh: More fun with arrays.
array=( zero one two three four five )
# Element 0 1 2 3 4 5
echo ${array[0]} # zero
echo ${array:0} # zero
# Parameter expansion of first element,
#+ starting at position # 0 (1st character).
echo ${array:1} # ero
# Parameter expansion of first element,
#+ starting at position # 1 (2nd character).
echo "--------------"
echo ${#array[0]} # 4
# Length of first element of array.
echo ${#array} # 4
# Length of first element of array.
# (Alternate notation)
echo ${#array[1]} # 3
# Length of second element of array.
# Arrays in Bash have zero-based indexing.
echo ${#array[*]} # 6
# Number of elements in array.
echo ${#array[@]} # 6
# Number of elements in array.
echo "--------------"
array2=( [0]="first element" [1]="second element" [3]="fourth element" )
echo ${array2[0]} # first element
echo ${array2[1]} # second element
echo ${array2[2]} #
# Skipped in initialization, and therefore null.
echo ${array2[3]} # fourth element
exit 0
gzgzgz 回复于:2005-04-14 23:59:07
不怕死,再灌#!/bin/bash
# array-strops.sh: String operations on arrays.
# Script by Michael Zick.
# Used with permission.
# In general, any string operation in the ${name ... } notation
#+ can be applied to all string elements in an array
#+ with the ${name[@] ... } or ${name[*] ...} notation.
arrayZ=( one two three four five five )
echo
# Trailing Substring Extraction
echo ${arrayZ[@]:0} # one two three four five five
# All elements.
echo ${arrayZ[@]:1} # two three four five five
# All elements following element[0].
echo ${arrayZ[@]:1:2} # two three
# Only the two elements after element[0].
echo "-----------------------"
# Substring Removal
# Removes shortest match from front of string(s),
#+ where the substring is a regular expression.
echo ${arrayZ[@]#f*r} # one two three five five
# Applied to all elements of the array.
# Matches "four" and removes it.
# Longest match from front of string(s)
echo ${arrayZ[@]##t*e} # one two four five five
# Applied to all elements of the array.
# Matches "three" and removes it.
# Shortest match from back of string(s)
echo ${arrayZ[@]%h*e} # one two t four five five
# Applied to all elements of the array.
# Matches "hree" and removes it.
# Longest match from back of string(s)
echo ${arrayZ[@]%%t*e} # one two four five five
# Applied to all elements of the array.
# Matches "three" and removes it.
echo "-----------------------"
# Substring Replacement
# Replace first occurance of substring with replacement
echo ${arrayZ[@]/fiv/XYZ} # one two three four XYZe XYZe
# Applied to all elements of the array.
# Replace all occurances of substring
echo ${arrayZ[@]//iv/YY} # one two three four fYYe fYYe
# Applied to all elements of the array.
# Delete all occurances of substring
# Not specifing a replacement means 'delete'
echo ${arrayZ[@]//fi/} # one two three four ve ve
# Applied to all elements of the array.
# Replace front-end occurances of substring
echo ${arrayZ[@]/#fi/XY} # one two three four XYve XYve
# Applied to all elements of the array.
# Replace back-end occurances of substring
echo ${arrayZ[@]/%ve/ZZ} # one two three four fiZZ fiZZ
# Applied to all elements of the array.
echo ${arrayZ[@]/%o/XX} # one twXX three four five five
# Why?
echo "-----------------------"
# Before reaching for awk (or anything else) --
# Recall:
# $( ... ) is command substitution.
# Functions run as a sub-process.
# Functions write their output to stdout.
# Assignment reads the function's stdout.
# The name[@] notation specifies a "for-each" operation.
newstr() {
echo -n "!!!"
}
echo ${arrayZ[@]/%e/$(newstr)}
# on!!! two thre!!! four fiv!!! fiv!!!
# Q.E.D: The replacement action is an 'assignment.'
# Accessing the "For-Each"
echo ${arrayZ[@]//*/$(newstr optional_arguments)}
# Now, if Bash would just pass the matched string as $0
#+ to the function being called . . .
echo
exit 0
一梦如是 回复于:2005-04-15 00:07:59
啥时候结束,提醒一声,偶好收藏~~
寂寞烈火 回复于:2005-04-15 00:08:54
引用:原帖由 "gzgzgz" 发表: newstr optional_arguments)}
# Now, if Bash would just pass the matched string as $0
#+ to the function being called . . .
echo
exit 0
:mrgreen: :mrgreen: OK! learning ...
gzgzgz 回复于:2005-04-15 09:32:28
:mrgreen: 数组的向后扩展# Try extending those arrays.
# Adding an element to an array.
array0=( "${array0[@]}" "new1" )
array1=( "${array1[@]}" "new1" )
array2=( "${array2[@]}" "new1" )
ListArray
# or
array0[${#array0[*]}]="new2"
array1[${#array1[*]}]="new2"
array2[${#array2[*]}]="new2
数组的拷贝与合并
#! /bin/bash
# CopyArray.sh
#
# This script written by Michael Zick.
# Used here with permission.
# How-To "Pass by Name & Return by Name"
#+ or "Building your own assignment statement".
CpArray_Mac() {
# Assignment Command Statement Builder
echo -n 'eval '
echo -n "$2" # Destination name
echo -n '=( ${'
echo -n "$1" # Source name
echo -n '[@]} )'
# That could all be a single command.
# Matter of style only.
}
declare -f CopyArray # Function "Pointer"
CopyArray=CpArray_Mac # Statement Builder
Hype()
{
# Hype the array named $1.
# (Splice it together with array containing "Really Rocks".)
# Return in array named $2.
local -a TMP
local -a hype=( Really Rocks )
$($CopyArray $1 TMP)
TMP=( ${TMP[@]} ${hype[@]} )
$($CopyArray TMP $2)
}
declare -a before=( Advanced Bash Scripting )
declare -a after
echo "Array Before = ${before[@]}"
Hype before after
echo "Array After = ${after[@]}"
# Too much hype?
echo "What ${after[@]:3:2}?"
declare -a modest=( ${after[@]:2:1} ${after[@]:3:2} )
# ---- substring extraction ----
echo "Array Modest = ${modest[@]}"
# What happened to 'before' ?
echo "Array Before = ${before[@]}"
exit 0
数组合并再一篇实例
#! /bin/bash
# array-append.bash
# Copyright (c) Michael S. Zick, 2003, All rights reserved.
# License: Unrestricted reuse in any form, for any purpose.
# Version: $ID$
#
# Slightly modified in formatting by M.C.
# Array operations are Bash-specific.
# Legacy UNIX /bin/sh lacks equivalents.
# Pipe the output of this script to 'more'
#+ so it doesn't scroll off the terminal.
# Subscript packed.
declare -a array1=( zero1 one1 two1 )
# Subscript sparse ([1] is not defined).
declare -a array2=( [0]=zero2 [2]=two2 [3]=three2 )
echo
echo '- Confirm that the array is really subscript sparse. -'
echo "Number of elements: 4" # Hard-coded for illustration.
for (( i = 0 ; i < 4 ; i++ ))
do
echo "Element [$i]: ${array2[$i]}"
done
# See also the more general code example in basics-reviewed.bash.
declare -a dest
# Combine (append) two arrays into a third array.
echo
echo 'Conditions: Unquoted, default IFS, All-Elements-Of operator'
echo '- Undefined elements not present, subscripts not maintained. -'
# # The undefined elements do not exist; they are not being dropped.
dest=( ${array1[@]} ${array2[@]} )
# dest=${array1[@]}${array2[@]} # Strange results, possibly a bug.
# Now, list the result.
echo
echo '- - Testing Array Append - -'
cnt=${#dest[@]}
echo "Number of elements: $cnt"
for (( i = 0 ; i < cnt ; i++ ))
do
echo "Element [$i]: ${dest[$i]}"
done
# Assign an array to a single array element (twice).
dest[0]=${array1[@]}
dest[1]=${array2[@]}
# List the result.
echo
echo '- - Testing modified array - -'
cnt=${#dest[@]}
echo "Number of elements: $cnt"
for (( i = 0 ; i < cnt ; i++ ))
do
echo "Element [$i]: ${dest[$i]}"
done
# Examine the modified second element.
echo
echo '- - Reassign and list second element - -'
declare -a subArray=${dest[1]}
cnt=${#subArray[@]}
echo "Number of elements: $cnt"
for (( i = 0 ; i < cnt ; i++ ))
do
echo "Element [$i]: ${subArray[$i]}"
done
# The assignment of an entire array to a single element
#+ of another array using the '=${ ... }' array assignment
#+ has converted the array being assigned into a string,
#+ with the elements separated by a space (the first character of IFS).
# If the original elements didn't contain whitespace . . .
# If the original array isn't subscript sparse . . .
# Then we could get the original array structure back again.
# Restore from the modified second element.
echo
echo '- - Listing restored element - -'
declare -a subArray=( ${dest[1]} )
cnt=${#subArray[@]}
echo "Number of elements: $cnt"
for (( i = 0 ; i < cnt ; i++ ))
do
echo "Element [$i]: ${subArray[$i]}"
done
echo '- - Do not depend on this behavior. - -'
echo '- - This behavior is subject to change - -'
echo '- - in versions of Bash newer than version 2.05b - -'
# MSZ: Sorry about any earlier confusion folks.
exit 0
:em11: 冒泡排序
#!/bin/bash
# bubble.sh: Bubble sort, of sorts.
# Recall the algorithm for a bubble sort. In this particular version...
# With each successive pass through the array to be sorted,
#+ compare two adjacent elements, and swap them if out of order.
# At the end of the first pass, the "heaviest" element has sunk to bottom.
# At the end of the second pass, the next "heaviest" one has sunk next to bottom.
# And so forth.
# This means that each successive pass needs to traverse less of the array.
# You will therefore notice a speeding up in the printing of the later passes.
exchange()
{
# Swaps two members of the array.
local temp=${Countries[$1]} # Temporary storage
#+ for element getting swapped out.
Countries[$1]=${Countries[$2]}
Countries[$2]=$temp
return
}
declare -a Countries # Declare array,
#+ optional here since it's initialized below.
# Is it permissable to split an array variable over multiple lines
#+ using an escape (\)?
# Yes.
Countries=(Netherlands Ukraine Zaire Turkey Russia Yemen Syria \
Brazil Argentina Nicaragua Japan Mexico Venezuela Greece England \
Israel Peru Canada Oman Denmark Wales France Kenya \
Xanadu Qatar Liechtenstein Hungary)
# "Xanadu" is the mythical place where, according to Coleridge,
#+ Kubla Khan did a pleasure dome decree.
clear # Clear the screen to start with.
echo "0: ${Countries[*]}" # List entire array at pass 0.
number_of_elements=${#Countries[@]}
let "comparisons = $number_of_elements - 1"
count=1 # Pass number.
while [ "$comparisons" -gt 0 ] # Beginning of outer loop
do
index=0 # Reset index to start of array after each pass.
while [ "$index" -lt "$comparisons" ] # Beginning of inner loop
do
if [ ${Countries[$index]} \> ${Countries[`expr $index + 1`]} ]
# If out of order...
# Recalling that \> is ASCII comparison operator
#+ within single brackets.
# if [[ ${Countries[$index]} > ${Countries[`expr $index + 1`]} ]]
#+ also works.
then
exchange $index `expr $index + 1` # Swap.
fi
let "index += 1"
done # End of inner loop
# ----------------------------------------------------------------------
# Paulo Marcel Coelho Aragao suggests for-loops as a simpler altenative.
#
# for (( last = $number_of_elements - 1 ; last > 1 ; last-- ))
# do
# for (( i = 0 ; i < last ; i++ ))
# do
# [[ "${Countries[$i]}" > "${Countries[$((i+1))]}" ]] \
# && exchange $i $((i+1))
# done
# done
# ----------------------------------------------------------------------
let "comparisons -= 1" # Since "heaviest" element bubbles to bottom,
#+ we need do one less comparison each pass.
echo
echo "$count: ${Countries[@]}" # Print resultant array at end of each pass.
echo
let "count += 1" # Increment pass count.
done # End of outer loop
# All done.
exit 0
灌了这么多怕是要被斑竹打出去了 :em06:
|