В этом ответе я дам только общие советы, а не тесты. Бенчмарки — единственный способ достоверно ответить на вопросы о производительности. Но так как вы не говорите сколько данных вы обрабатываете и как часто вы выполняете эту операцию, нет никакого способа провести полезный тест. Что более эффективно для 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, если в вашей системе есть dash или ksh как sh
, а не bash. Если вы используете 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
«Имена файлов с пробелами» требуют find
и xargs
. Прочтите man find xargs
и сделайте что-то вроде
find Fixed_Zip -type f -name '*.ipynb' -print0 | \
xargs -0 -r -n 1 jupytext --to py