Редактировать: добавлено сравнение времени (в конце) и избавлено от tr
Можно заменить содержимое элементов массива, используя bash Расширение параметра , т.е. ${var[@]....}
но вы не можете удалить элементы. Лучшее, что вы можете получить с расширением параметров, это сделать пустыми ("") те элементы, которые вам не нужны.
Вместо этого вы можете использовать printf
, sed
и IFS
. Преимущество этого состоит в том, что вы можете использовать полный синтаксис регулярных выражений (а не только выражения глобализации оболочки) ... и это на намного быстрее, чем при использовании цикла ...
Этот пример оставляет элементы массива, которые содержат c
Примечание: Этот метод обслуживает пробелы в данных. Это достигается с помощью IFS=\n
IFS=$'\n'; a=($(printf '%s\n' "${a[@]}" |sed '/c/!d'))
Здесь снова с дампами до / после:
#!/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
========
Для общего ознакомления: тестирование массива, содержащего 10 тыс. Элементов. выбрав 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'))
1-й цикл метод:
iz=${#a[@]}; j=0
for ((i=0; i<iz; i++)) ;do
[[ ! "${a[i]}" =~ .*[5-9]...$ ]] && unset a[$i]
done
2-й цикл метод:
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