Есть ли более элегантный способ подсчета слов и присвоение этому числу переменных?

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

#!/bin/bash /root/xiotech status > xiostatus.tmp SyncCount=$(grep -c Sync xiostatus.tmp) PauseCount=$(grep -c paused xiostatus.tmp) CopyingCount=$(grep -c Copying xiostatus.tmp) if [ "$SyncCount" -eq "11" ] then echo All 11 mirrors are in sync. else echo $PauseCount mirrors are paused and $CopyingCount mirrors are syncing. fi rm -f xiostatus.tmp 

Есть ли более элегантный способ подсчета и «переменный-размер» этих счетчиков, используя что-то вроде awk? В этом случае файл крошечный, так что это не очень важно, но если файл был 900mb, потребуется 3 дополнительных цикла, чтобы пройти его 3 раза …

3 Solutions collect form web for “Есть ли более элегантный способ подсчета слов и присвоение этому числу переменных?”

awk может легко заменить весь скрипт:

 #!/usr/bin/awk -f /Sync/ {SyncCount++} /paused/ {PauseCount++} /Copying/ {CopyingCount++} END { if(SyncCount == 11) print "All 11 mirrors are in sync." else print (+PauseCount) " mirrors are paused and " (+CopyingCount) " mirrors are syncing." } 

(+var) – заставить awk обрабатывать переменную как число (поэтому она будет выводить 0 если переменная была отключена). Вы также можете использовать блок BEGIN чтобы сначала установить все переменные в 0 :

 BEGIN { SyncCount = PauseCount = CopyingCount = 0 } 

Вставьте файл в файл и запустите awk -f /path/to/the/script.awk xiostatus.tmp . Если вам не нужен временный файл, вы можете даже сделать /root/xiotech status | awk -f /path/to/the/script.awk /root/xiotech status | awk -f /path/to/the/script.awk .

Если вы установите бит выполнения на awk скрипте, вы можете назвать его автономным исполняемым файлом: /path/to/the/script.awk xiostatus.tmp или /root/xiotech status | /path/to/the/script.awk /root/xiotech status | /path/to/the/script.awk .

Для тех, кто хочет подсчитать все экземпляры, вот версия awk, которая будет считать несколько неперекрывающихся экземпляров, когда на одной строке больше одной

UPDATE: теперь я включил другой метод, который использует split(... .Это намного быстрее, чем match( substr(... метод match( substr(... ), который теперь указан ниже более быстрого. Метод split(... больше 4 раз быстрее, чем другие … (проверено на 87 файлов в общей сложности 407 612 строк.
Для дальнейшего сравнения метод Майкла Мрозека с использованием /Sync/ range-selection (который подсчитывает строки, контактирующие с каждым шаблоном, и подсчет всех экземпляров шаблона) в два раза быстрее, чем этот новый метод (для тех же данных).

Еще одно преимущество (?) Преимущества этого более быстрого split(methos) заключается в том, что он довольно терпим к недопустимым символам UTF-8 в файле (пока они не находятся в шаблоне разделителя) … Разделители сами являются фактической строкой шаблоны … Несколько из моих тестовых файлов имели в них недопустимый UTF-8, и мне потребовалось довольно много времени, чтобы узнать, почему у меня разные результаты от двух методов.
После того, как файлы проблем были перекодированы в действительный UTF-8, оба метода дают идентичные результаты.

Вот новый более быстрый метод (в 4 раза быстрее) … с помощью split(...

 #!/bin/bash pat='xx|yy|zz' awk -v vpat="$pat" 'BEGIN { split(vpat, pat, "|"); for(i in pat) pz++ } { if (NF) { for( p in pat ) { ct[p]+=(split( $0, A, pat[p] ) -1) }} } END { print " count pattern" for (p=1; p<=pz; p++) { printf "%6d %s\n", +ct[p], pat[p] } }' file 

Вот более медленный метод. используя match( substr(...

 #!/bin/bash # Count occurrences of multiple non-overlapping string patterns awk 'BEGIN { pattern[1]="xx" pattern[2]="yy" pattern[3]="zz" } { for( p in pattern ) { LHB=0; RSTART=RLENGTH=1 while( match( substr( $0, LHB+=(RSTART+RLENGTH-1)), pattern[p] )){ count[p]++ } } } END { print "occurs pattern" for (p in pattern) { printf "%6d %s\n", +count[p], pattern[p] } }' file 

Вот входной файл

 xx xx xx xx yy xx 

Вывод выглядит следующим образом:

 occurs pattern 5 xx 1 yy 0 zz 

Как насчет:

 eval `/root/xiotech status | grep -Eo 'Sync|paused|Copying' | sort | uniq -c | awk '{print "count_" $2 "=" $1}'` if [ "$count_Sync" -eq 11 ]; then echo All 11 mirrors are in sync. else echo $count_paused mirrors are paused and $count_Copying mirrors are syncing. fi 

grep -Eo позволяет искать несколько шаблонов (разделенных grep -Eo «|») и возвращает только строку, которая соответствует. sort | uniq -c sort | uniq -c показывает количество найденных слов. Скрипт awk форматирует новые команды оболочки для создания переменных, начинающихся с «count_». И, наконец, eval примет созданные команды оболочки и оценит их в оболочке.

  • Как передать содержимое файла в виде нескольких аргументов в bash
  • Как я могу генерировать случайное 64-битное целое число со знаком с macOS?
  • Выход прерывается при добавлении вывода sql-запроса в ksh
  • Условно включить этап трубы в сценарии bash
  • сохранить дубликаты из $ PATH на источнике
  • Передача нескольких varibles скрипту для SQL-запроса
  • Добавить определенные слова в файл
  • Программа оболочки, которая считывает строки и выходные строки с номерами строк
  • Попытка присвоения не переменной?
  • Как запустить исполняемый файл Windows в сценарии оболочки Linux?
  • как совместить слова и игнорировать пробелы
  • Linux и Unix - лучшая ОС в мире.