Невероятно медленная петля bash - PullRequest
0 голосов
/ 08 июня 2018

Я сделал быструю вещь, просто вставив некоторые команды в функцию и зацикливая файл и запуская его для каждой строки.Я поражен медленной скоростью, которую он достигает.

Есть какие-нибудь предложения относительно того, как я могу ускорить этот цикл, который использует вонючую функцию?

#!/bin/bash
list="lists/test.txt"

smellyfunc() {

alphabet=abcdefghijklmnopqrstuvwxyz
bgam=bcdefghijklmnopqrstuvwxyz
plaintext=THXGAWDITSFRIDAYTODAY
plaintext=$(echo "$plaintext" | tr A-Z a-z | sed s/[^a-z]//g) 
step=0

while test -n "$plaintext"
do
  key=$1
  length=${#key}
  char=${plaintext:0:1}
  shift=${key:$step:1}
  code=$(echo -n $(($(expr index $bgam $char)-$(expr index $bgam $shift))))
  step=$(($(($step+1))%$length))
  if [[ $code -lt 0 ]]
    then
    code=$((code+26))
  fi
  if [[ $code -gt 25 ]]
    then
    code=$((code-26))
  fi
  echo -n ${alphabet:$code:1}
  plaintext=${plaintext:1}
done
}

while read line; do
   key="$line"
   result="$(smellyfunc "$key")"
   echo "$result" "$key"
done < $list

Спасибо!

1 Ответ

0 голосов
/ 08 июня 2018

Если мы переписываем так, что вам не нужно вызывать какие-либо внешние программы, и вы экономите, отражая вывод, мы можем получить большое ускорение:

# function to mimic `expr index`
index() {
    local prefix=${1%%$2*}
    local i=${#prefix}
    if [[ $prefix == $1 ]]; then
        # substring $2 not found in $1
        i=-1
    fi
    echo $((i+1))
}

aromaticfunc() {
    local alphabet=abcdefghijklmnopqrstuvwxyz
    local bgam=bcdefghijklmnopqrstuvwxyz
    local step=0
    local -l plaintext=THXGAWDITSFRIDAYTODAY
    plaintext=${plaintext//[^a-z]/}
    local key length char shift code
    local result=""

    while [[ -n $plaintext ]]; do
        key=$1
        length=${#key}
        char=${plaintext:0:1}
        plaintext=${plaintext:1}
        shift=${key:$step:1}
        code=$(( $(index $bgam $char) - $(index $bgam "$shift") ))
        code=$(( (code+26) % 26 ))
        step=$(( (step+1) % length ))
        result+=${alphabet:$code:1}
    done
    echo "$result"
}

, тогда посмотрим, получим ли мытот же результат:

$ s=$( smellyfunc helloworld )
$ a=$( aromaticfunc helloworld )
$ [[ $s == $a ]] && echo OK || echo different
OK

и, чтобы ответить на вопрос, это быстрее?

$ time for i in {1..100}; do result=$(smellyfunc helloworld); done 

real    0m7.339s
user    0m5.739s
sys 0m0.967s
$ time for i in {1..100}; do result=$(aromaticfunc helloworld); done 

real    0m2.725s
user    0m1.879s
sys 0m0.613s

Итак, примерно в 3 раза ускорение.

...