Vou apenas dar alguns conselhos gerais nesta resposta, e não referências. Os benchmarks são a única maneira de responder com segurança a perguntas sobre desempenho. Mas como você não diz quantos dados está manipulando e com que frequência executa essa operação, não há como fazer uma referência útil. O que é mais eficiente para 10 itens e o que é mais eficiente para 1000000 itens geralmente não é o mesmo.
Como regra geral, invocar comandos externos é mais caro do que fazer algo com construções de shell puras, desde que o código de shell puro não envolva um loop. Por outro lado, é provável que um loop de shell que itere sobre uma string grande ou uma grande quantidade de string seja mais lento que uma chamada de uma ferramenta para fins especiais. Por exemplo, sua chamada de loop cut
pode muito bem ser prática na prática, mas se você encontrar uma maneira de fazer a coisa toda com uma única cut
chamada, provavelmente será mais rápida do que fazer a mesma coisa com a manipulação de strings no shell.
Observe que o ponto de corte pode variar muito entre os sistemas. Pode depender do kernel, de como o agendador do kernel está configurado, do sistema de arquivos que contém os executáveis externos, da quantidade de CPU versus pressão de memória existente no momento e de muitos outros fatores.
Não ligue expr
para executar aritmética se você estiver preocupado com o desempenho. Na verdade, não ligue expr
para executar aritmética. Os shells possuem aritmética embutida, mais clara e mais rápida do que a chamada expr
.
Você parece estar usando o bash, já que está usando construções do bash que não existem no sh. Então, por que diabos você não usaria uma matriz? Uma matriz é a solução mais natural e provavelmente também a mais rápida. Observe que os índices da matriz começam em 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
Seu script pode muito bem ser mais rápido se você usar sh, se seu sistema tiver traço ou ksh em sh
vez de bash. Se você usa sh, não recebe matrizes nomeadas, mas ainda obtém a matriz com um dos parâmetros posicionais, com os quais você pode definir set
. Para acessar um elemento em uma posição que não é conhecida até o tempo de execução, você precisa usar eval
(lembre-se de citar as coisas corretamente!).
# 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
Se você quiser acessar a matriz apenas uma vez e estiver indo da esquerda para a direita (pulando alguns valores), poderá usar em shift
vez de índices variáveis.
# 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
Qual abordagem é mais rápida depende do shell e do número de elementos.
Outra possibilidade é usar o processamento de strings. Tem a vantagem de não usar os parâmetros posicionais, para que você possa usá-los para outra coisa. Será mais lento para grandes quantidades de dados, mas é improvável que faça uma diferença notável para pequenas quantidades de dados.
# 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