В этом ответе я дам лишь общие советы, а не тесты. Тесты - это единственный способ достоверно ответить на вопросы о производительности. Но так как вы не говорите, сколько данных вы манипулируете и как часто вы выполняете эту операцию, нет никакого способа сделать полезный тест. Что более эффективно для 10 предметов, а что более эффективно для 1000000 предметов, зачастую не одно и то же.
Как общее правило, вызов внешних команд обходится дороже, чем выполнение каких-либо операций с чистыми конструкциями оболочки, если чистый код оболочки не включает цикл. С другой стороны, цикл оболочки, который выполняет итерации по большой строке или большому количеству строки, вероятно, будет медленнее, чем один вызов специального инструмента. Например, ваш вызов цикла cut
на практике может быть заметно медленным, но если вы найдете способ сделать все это одним cut
вызовом, это, вероятно, будет быстрее, чем то же самое с манипулированием строками в оболочке.
Обратите внимание, что точка отсечки может сильно различаться в разных системах. Это может зависеть от ядра, от того, как настроен планировщик ядра, от файловой системы, содержащей внешние исполняемые файлы, от того, какая нагрузка на ЦП и память в данный момент существует, и от многих других факторов.
Не звоните, expr
чтобы выполнить арифметику, если вас вообще беспокоит производительность. На самом деле, не призывайте expr
выполнять арифметику вообще. Оболочки имеют встроенную арифметику, которая понятнее и быстрее, чем вызов expr
.
Кажется, вы используете bash, поскольку вы используете конструкции bash, которых нет в sh. Так почему же вы не используете массив? Массив является наиболее естественным решением, и, вероятно, он также будет самым быстрым. Обратите внимание, что индексы массива начинаются с 0.
list=(1 2 3 5 9 8 6 90 84 9 3 2 15 75 55)
for ((count = 0; count += 3; count < ${#list[@]})); do
echo "${list[$count]}"
done
Ваш скрипт может быть быстрее, если вы используете sh, если в вашей системе sh
вместо bash используется dash или ksh . Если вы используете sh, вы не получите именованные массивы, но вы все равно получите массив с одним из позиционных параметров, который вы можете установить set
. Чтобы получить доступ к элементу в позиции, которая не известна до времени выполнения, вам нужно использовать eval
(позаботьтесь о правильном цитировании!).
# List elements must not contain whitespace or ?*\[
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
set $list
count=1
while [ $count -le $# ]; do
eval "value=\${$count}"
echo "$value"
count=$((count+1))
done
Если вы когда-нибудь захотите получить доступ к массиву только один раз и идете слева направо (пропуская некоторые значения), вы можете использовать shift
вместо переменных индексы.
# List elements must not contain whitespace or ?*\[
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
set $list
while [ $# -ge 1 ]; do
echo "$1"
shift && shift && shift
done
Какой подход быстрее, зависит от оболочки и количества элементов.
Другая возможность - использовать обработку строк. Он имеет преимущество в том, что не использует позиционные параметры, поэтому вы можете использовать их для чего-то другого. Это будет медленнее для больших объемов данных, но вряд ли это будет заметно для небольших объемов данных.
# List elements must be separated by a single space (not arbitrary whitespace)
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
while [ -n "$list" ]; do
echo "${list% *}"
case "$list" in *\ *\ *\ *) :;; *) break;; esac
list="${list#* * * }"
done