Бывает так, что от bash-скрипта требуется скорость. Хорошая такая скорость, поскольку скрипт вызывается, скажем, 50-60 раз в секунду и работает с текстом. При этом должна быть возможность всё быстро исправлять, поэтому да, мы не будем переписывать это на C.

Откажитесь от внешних программ

Множество действий можно сделать силами bash, без вызова внешних программ - sed, awk, grep. Суть в том, что на запуск внешней программы тратится время - открытие бинарика, передача ему параметров и всё такое. Казалось бы мелочь, ~0.05мс, но когда у вас grep вызывается внутри while read line; do   if echo $line | grep няшный; then      echo $line | sed -e ‘s/котик/кот/g’   fidone < $file > ${file}.fixedПардон за пример, с утра ничего в голову особо не лезет кроме котиков.При наличии пачки крупных файлов это дело будет работать очень долго. Но что делать? Заменить вызов внешних команд на bash’евые build-in где это только возможно!while read line; do   if [[ “$line” = няшный ]]; then      echo ${line//котик/кот}   fidone < $file > ${file}.fixedПримеры замен:

echo | grep

if echo $line | grep -q $word; thenможно заменить на:[[ “$line” = $word ]]

awk

awk ‘${print $3” “$5}’ $fileможно заменить на (Тем не менее, иногда натравливать внешние программы оказывается быстрее. При работе с большими (более 1000 строк) файлами вывод части колонок лучше сделать при помощи awk, либо cut, если IFS один.while read tmp tmp word1 tmp word2 tmp; do   echo $word1 $word2done < $file

var=$(echo | sed)

Не стоит также вызывать sed ради простейших замен в переменной:s=”$(echo $line | sed ‘s/котик/кот/g’)”лучше сделать это с помощью bash’евских подстановокs=${line//что-то/другое}если нужно удалить что-то:s=${line#a}- всё до первого попадения a с началаs=${line##a}- всё до последнего попадения a с началаs=${line%a} - всё с конца до последнего попадения as=${line%%a} - всё с конца до первого попадения as=${line/a/} - удалить первую a (заменить на пустоту)s=${line//a/} - удалить все a (заменить на пустоту)

Не обрабатывайте вывод запроса к БД регулярками

bash-4.1# echo -e “SELECT first 10 id FROM users;\n” | isql-fb -q  /var/db/billing.gdb  -p something -u SYSDBA          ID ============            2            1          306          287          288          312          313          293          295          296 А нам, скажем нужны только id для while read. Так вот, не стоит делать что-то в духе:echo -e “SELECT first 10 id FROM users;\n” | isql-fb -q  /var/db/billing.gdb  -p something -u SYSDBA > fileegrep -v “(ID|=========|^\s\t$)” file > file2while read line; do   действия над $linedone < file2Гораздо быстрее, универсальнее и безопаснее будет поступить так:echo -e “SELECT first 10 ‘rowrow’, id FROM users;\n” | isql-fb -q  /var/db/billing.gdb  -p something -u SYSDBA > filegrep rowrow file | while read line; do   действия над $linedoneКстати, не знаю откуда у меня такое пошло, но мне гораздо более привычно, когда stdin / stdout у while-loop задаются после done, даже если это результат команды, чем передача через пайп сверху, например:while read line; do  echo $linedone «< “$(iptables -nvL)” > fileХотя вообще - такая конструкция зло. Лучше скидывать всё в файл заранее:iptables -nvL > filewhile read line; do  echo $linedone < file > file2

Откажитесь или уменьшите sleep

Вместо того, чтобы заставлять код сидеть на месте, лучше заставьте его в это время сделать всё, что не зависит от того, чего вы ждёте. Вполне возможно, что это занимает достаточно много времени и позволит установить время ожидания немного меньше или ещё лучше, отказаться от него.К сожалению примера под рукой сейчас нет.

Параллельте

Если ваш файл делает несколько задач, которые не зависят друг от друга и выводит их результаты, но при этом каждая из них выполняется несколько секунд, например что-то в духе:#!/bin/bashjob1() {   ping -c 4 8.8.8.8}job2() {   for table in filter nat mangle; do      iptables -t $table -F   done}job3() {  timeout -9 5 tcpdump -nvi any tcp port 3050}job1job2job3сделайте что-то в духе:main() {   { job1 &> /tmp/job1 } &   { job2 &> /tmp/job2 } &   { job3 &> /tmp/job3 } &   wait   cat /tmp/job*}main