W tej odpowiedzi udzielę jedynie ogólnych wskazówek, a nie punktów odniesienia. Testy porównawcze to jedyny sposób, aby rzetelnie odpowiedzieć na pytania dotyczące wydajności. Ale ponieważ nie mówisz, ile danych manipulujesz i jak często wykonujesz tę operację, nie ma sposobu na wykonanie użytecznego testu porównawczego. Co jest bardziej wydajne dla 10 przedmiotów, a co jest bardziej wydajne dla 1000000 przedmiotów, często nie jest takie samo.
Ogólna zasada polega na tym, że wywoływanie zewnętrznych poleceń jest droższe niż robienie czegoś przy użyciu czystych konstrukcji powłoki, o ile czysty kod powłoki nie wymaga pętli. Z drugiej strony pętla powłoki, która iteruje po dużym łańcuchu lub dużej ilości łańcucha, może być wolniejsza niż jedno wywołanie narzędzia specjalnego. Na przykład, wywoływanie pętli cut
może być zauważalnie powolne w praktyce, ale jeśli znajdziesz sposób na zrobienie wszystkiego za pomocą pojedynczego cut
wywołania, które prawdopodobnie będzie szybsze niż robienie tego samego z manipulowaniem łańcuchem w powłoce.
Należy pamiętać, że punkt odcięcia może się znacznie różnić między systemami. Może zależeć od jądra, od konfiguracji harmonogramu jądra, od systemu plików zawierającego zewnętrzne pliki wykonywalne, od tego, ile procesora w tej chwili naciska pamięć, i od wielu innych czynników.
Nie dzwoń, expr
aby wykonać arytmetykę, jeśli w ogóle martwisz się wydajnością. W rzeczywistości nie wzywaj expr
do wykonywania arytmetyki. Pociski mają wbudowaną arytmetykę, która jest wyraźniejsza i szybsza niż wywoływanie expr
.
Wygląda na to, że używasz basha, ponieważ używasz konstrukcji bash, które nie istnieją w sh. Dlaczego więc, do cholery, nie miałbyś użyć tablicy? Tablica jest najbardziej naturalnym rozwiązaniem i prawdopodobnie też będzie najszybsza. Zauważ, że indeksy tablic zaczynają się od 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
Twój skrypt może być szybszy, jeśli używasz sh, jeśli twój system ma kreskę lub ksh sh
zamiast zamiast bash. Jeśli używasz sh, nie otrzymujesz nazwanych tablic, ale nadal otrzymujesz tablicę jednego z parametrów pozycyjnych, które możesz ustawić set
. Aby uzyskać dostęp do elementu w pozycji, która nie jest znana przed uruchomieniem, musisz użyć eval
(zadbaj o prawidłowe cytowanie rzeczy!).
# 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
Jeśli kiedykolwiek chcesz uzyskać dostęp do tablicy tylko raz i przechodzisz od lewej do prawej (pomijając niektóre wartości), możesz użyć shift
zamiast indeksów zmiennych.
# 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
To, które podejście jest szybsze, zależy od powłoki i liczby elementów.
Inną możliwością jest użycie przetwarzania ciągów. Ma tę zaletę, że nie używa parametrów pozycyjnych, więc możesz użyć ich do czegoś innego. Będzie działać wolniej w przypadku dużych ilości danych, ale jest mało prawdopodobne, aby zauważalna różnica w przypadku małych ilości danych.
# 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