编辑:添加了时间比较(在结尾处)并且去掉了tr
使用bash的参数扩展,即${var[@]....}
可以替换数组元素的内容,但你不能真正地删除元素。最好的方法是使用参数扩展使你不需要的元素变为空("")。
相反地,你可以使用printf
、sed
和IFS
。这样做有一个优点,允许你使用完整的正则表达式语法(而不仅仅是shell通配符表达式),同时比使用循环快得多。
这个例子会保留包含c
的数组元素。
注意:此方法适用于数据中包含空格的情况,这是通过IFS=\n
实现的。
IFS=$'\n'; a=($(printf '%s\n' "${a[@]}" |sed '/c/!d'))
以下是带有before/after dumps的内容:
#!/bin/bash
a=(one.ac two.b tree.c four.b "five b abcdefg" )
echo "======== Original array ===="
printf '%s\n' "${a[@]}"
echo "======== Array containing only the matched elements 'c' ===="
IFS=$'\n'; a=($(printf '%s\n' "${a[@]}" |sed '/c/!d'))
printf '%s\n' "${a[@]}"
echo "========"
输出:
======== Original array ====
one.ac
two.b
tree.c
four.b
five b abcdefg
======== Array containing only the matched elements 'c' ====
one.ac
tree.c
five b abcdefg
========
一般参考:测试包含10k个元素的数组。选择其中5k个:
a=( a\ \ \ \ b{0..9999} )
printf方法耗时:0m0.226s
(结果为顺序索引值)
第一种循环方法:0m4.007s
(它在索引值中留下空隙)
第二种循环方法:0m7.862s
(结果为顺序索引值)
printf方法:
IFS=$'\n'; a=($(printf '%s\n' "${a[@]}" |sed '/.*[5-9]...$/!d'))
第一种循环方法:
iz=${#a[@]}; j=0
for ((i=0; i<iz; i++)) ;do
[[ ! "${a[i]}" =~ .*[5-9]...$ ]] && unset a[$i]
done
第二种循环方法:
iz=${#a[@]}; j=0
for ((i=0; i<iz; i++)) ;do
if [[ ! "${a[i]}" =~ .*[5-9]...$ ]] ;then
unset a[$i]
else
a[$j]="${a[i]}=$i=$j"; ((j!=i)) && unset a[$i]; ((j+=1));
fi
done