Как избежать повторения одной и той же команды в сценарии bash

У меня есть сценарий bash:

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/ath_bstuck_tasklet/ { print $4 }' | sort | uniq -c > /tmp/netgear_beacon.txt echo "There are `wc -l /tmp/netgear_beacon.txt | awk '{print $1}'` Stuck beacon; resetting" >> /tmp/netgear_beacon.txt gunzip -c /var/log/cisco/cisco.log-`date +%Y%m%d`.gz | awk '/Virtual device ath0 asks to queue packet/ { print $4 }' | sort | uniq -c > /tmp/netgear_buffer_queue.txt echo "There are `wc -l /tmp/netgear_buffer_queue.txt | awk '{print $1}'` routers with 'Virtual device ath0 asks to queue packet' errors" >> /tmp/netgear_buffer_queue.txt gunzip -c /var/log/cisco/cisco.log-`date +%Y%m%d`.gz | awk '/CMS_MSG_DNSPROXY_RELOAD/ { print $4 }' | sort | uniq -c > /tmp/netgear_dns.txt echo "There are `wc -l /tmp/netgear_dns.txt | awk '{print $1}'` routers with 'DNS Proxy Issue' errors" >> /tmp/netgear_dns.txt gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/beacon/ { print $4 }' | sort | uniq -c > /tmp/netgear_beacon_frame.txt echo "There are `wc -l /tmp/netgear_beacon_frame.txt | awk '{print $1}'` routers with beacon frame errors" >> /tmp/netgear_beacon_frame.txt gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/ACK/ { print $4 }' | sort | uniq -c | awk -vx=50 '$1 >= x' > /tmp/netgear_ACK.txt echo "There are `wc -l /tmp/netgear_ACK.txt | awk '{print $1}'` routers with more than 50 ACK" >> /tmp/netgear_ACK.txt 

Я бы старался не повторять команду gunzip каждый раз. Я буду запускать его только один раз и использовать его для всех шагов. Я думал о переменной, но это лучшая практика?

2 Solutions collect form web for “Как избежать повторения одной и той же команды в сценарии bash”

Нет «лучших практик». Только то, что имеет смысл и облегчает жизнь.

Выделение общих частей и параметризация остальных – одна из таких вещей:

 lines="`gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz`" #gunzip would always output the same thing on the same day, so #just run it once and store the results in a variable grepAndLog(){ local regex="$1" file="$2" msg="$3" filter="${4:-cat}" #^names for positional parameters printf "%s\n" "$lines" | grep "$regex" | cut -d' ' -f4 | sort | uniq -c | eval "$filter" > "/tmp/$file" local count=`wc -l < "/tmp/$file"` echo "There are $count "" $msg" >> "/tmp/$file" } grepAndLog ath_bstuck_tasklet netgear_bacon.txt \ 'Stuck beacon; resetting' grepAndLog netgear_buffer_queue netgear_buffer_queue.txt \ "routers with 'Virtual device ath0 asks to queue packet' errors" grepAndLog CMS_MSG_DNSPROXY_RELOAD netgear_dns.txt \ " routers with 'DNS Proxy Issue' errors" grepAndLog ath_bstuck_tasklet netgear_bacon.txt \ " routers with beacon frame errors" grepAndLog ACK netgear_ACK.txt \ " routers with more than 50 ACK" 'awk -vx=50 "\$1 >= x"' 

Это все еще основное решение. Но ИМО более читабельна и на 40% короче.

О коде:

Я использую grep "$regex" | cut -d' ' -f4 grep "$regex" | cut -d' ' -f4 вместо выражения awk. Кроме того, функция grepAndLog является обобщением того, что вы делаете в каждой строке вашего скрипта: у вас есть ввод (вывод gunzip), вы grep для выражения (параметр $regex ) и выводящие результирующие строки, отсортировано и префикс счетчика в $file . Затем вы добавляете счетчик строк (я делаю wc -l < "$file" вместо wc -l "$file" | awk ... ), завернутый в сообщение, начало которого постоянное и конец которого изменяется ( $msg ).

В вашей последней строке вы не просто grep, но и используете другой фильтр. Вместо того, чтобы создавать ветвь if для этой функции, я просто использую cat как неявный дополнительный дополнительный фильтр в обычных случаях, когда не существует четвертого параметра ( local filter="${4:-cat}" означает создание функции-локального переменный фильтр, содержимое которого является четвертым параметром, заданным для функции, или cat если не указан четвертый параметр). cat получает overriden, если четвертый параметр присваивается grepAndLog .

Лучше всего здесь было бы выполнить всю обработку в одном awk . Что-то похожее на это:

 gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk ' /ath_bstuck_tasklet/ { netgear_beakon[$4] = 1 } /Virtual device ath0 asks to queue packet/ { netgear_buffer_queue[$4] = 1 } ... /ACK/ { netgear_ACK[$4] ++ } END { n=0; for(k in netgear_beakon) n++; print n,"Stuck beacon; resetting"; n=0; for(k in netgear_buffer_queue) n++; print n,"routers with Virtual device ath0 asks to queue packet"; ... n=0; for(k in netgear_ACK) n+=(netgear_ACK[k]>=50); print n,"routers with more than 50 ACK" }' 

В дополнение к исключению чтения файла более одного раза, это также исключает необходимость выполнения sort и uniq несколько раз. Это сохраняет (или подсчитывает) каждый уникальный элемент в массиве, а затем вычисляет количество элементов путем итерации по ключам каждого массива.

  • как получить # файлов, скопированных с помощью rsync
  • замена набора персонажей PIPE
  • Быстрый способ получить информацию из огромного файла журнала в unix
  • Необходимо отключить комментарии в двойных кавычках
  • Как я могу форматировать плоский файл с помощью awk?
  • Извлечение текстовых блоков на основе вывода grep
  • grep для n или более периодов на заданной строке
  • сопоставление и слияние строк с awk & печать с помощью Solaris
  • Условно разбить столбцы на 2 строки?
  • Удалить строки из файла, который существует в другом файле с более новой меткой времени
  • Как разбирать XML-файл в сценарии оболочки
  • Interesting Posts

    Force OpenSSH / pam / pam_ldapd для выполнения pam_ldapd (sshd: auth) с аутентификацией с открытым ключом

    Как вы создаете Linux ISO? (Вилка Debian)

    Когда FTP требует FTP через TLS, это FTPS?

    Сравните даты файлов с двумя каталогами

    Будет ли chmod 000 / dev / stdin отключить терминал навсегда?

    Размер файла, показанный «du -k», различен в разных файловых системах (PRAMFS и FLASH)

    Получение md5 во время wget

    Что делает Linux по-другому, что позволяет мне удалять / заменять файлы, в которых Windows будет жаловаться на файл, который в настоящее время используется?

    Смутно, когда нужно избегать метасимволов в дорожках

    Как я могу создать свой собственный файл орфографии для vim?

    Пакеты пропущены из-за проблем с зависимостями:

    Почему Enlightenment 17 (Debian 8) не показывает значок при подключении компакт-диска или USB-накопителя?

    Перекомпилируйте ядро, меняя только один параметр

    Есть что-то вроде генератора lorem ipsum?

    Как преобразовать данные с разделителями табуляции в данные с разделителями-запятыми?

    Linux и Unix - лучшая ОС в мире.