Как суммировать повторяющиеся строки

#awk

#awk

Вопрос:

Мой входной файл: ( дублированный UUID (например: WW000001 ), указанный как в HBA0, так и в HBA1, и оба они имеют уникальное имя, например: /dev/sda и /dev/sde )

 /dev/sda HBA0 WW000001
/dev/sdb HBA0 WW000002
/dev/sdc HBA0 WW000003
/dev/sdd HBA0 WW000004
/dev/sde HBA1 WW000001
/dev/sdf HBA1 WW000002
/dev/sdg HBA1 WW000003
/dev/sdh HBA1 WW000004
  

Тот же UUID (например: /dev/sda и /dev/sde ) означает фактически тот же диск, но с другим именем диска и путем HBA.

Я хочу получить сбалансированный список (уникальный UUID, указанный сбалансированным в HBA0 и HBA1 ). Последовательность не имеет значения, если UUID уникален в конечном результате, а у HBA0 и HBA1 одинаковые номера дисков.

пример:

 /dev/sda HBA0 WW000001
/dev/sdb HBA0 WW000002
/dev/sdg HBA1 WW000003
/dev/sdh HBA1 WW000004
  

наконец, я получу сбалансированный список:

 /dev/sda
/dev/sdb
/dev/sdg
/dev/dfh
  

Комментарии:

1. Не могли бы вы подробнее рассказать о логике того, как диски /dev/sda и /dev/sde одинаковы?

2. В MPIO они одинаковы, когда UUID одинаковый.

3. Таким образом, это означает, что либо /dev/sdc печатается, либо /dev/sdg печатается, для вас это не имеет значения? (Я не верю), извините, просто пытаюсь понять логику, с помощью которой вы хотите напечатать строки.

4. да, это имеет значение, поскольку их HBA отличается.

Ответ №1:

Не могли бы вы попробовать следующее:

 awk '{
    dev[$2,$3] = $1                     # make device list indexed by HBA and UUID
    uuid[$3]                            # make UUID list
}
END {
    j = 0                               # reset HBA number
    for (i in uuid) {                   # loop over UUID list
        hba = "HBA" j                   # "HBA0" or "HBA1"
        print dev[hba,i], hba, i        # print the list
        j = xor(j, 1)                   # flip between "0" and "1"
    }
}' inputfile
  

Результат:

 /dev/sda HBA0 WW000001
/dev/sdf HBA1 WW000002
/dev/sdc HBA0 WW000003
/dev/sdh HBA1 WW000004
  

Чтобы получить balanced список, он изменяет значение HBA между HBA0 и HBA1 один за другим.
Последовательность устройств отличается от опубликованного примера, но я надеюсь, что она будет соответствовать вашим требованиям.

Ответ №2:

Вы можете либо отсортировать свой файл, если он не отсортирован, а затем использовать комбинацию head , tail , и wc , чтобы выбрать сбалансированные (четное количество) строк из начала и конца вашего файла, например

 $ head -n$(($(wc -l < file) / 4)) file; tail -n$(($(wc -l < file) / 4)) file
/dev/sda HBA0 WW000001
/dev/sdb HBA0 WW000002
/dev/sdg HBA1 WW000003
/dev/sdh HBA1 WW000004
  

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

Если вам нужно сначала отсортировать, то sort -k1,8 file это будет сделано, и поскольку вы отметили свой вопрос [bash] , вы можете просто использовать замену процесса для final file в каждой из двух команд, например < <(sort -k1,8 file) .

Чтобы получить окончательный список, просто выберите первое поле с cut помощью, например

 $ cut -d' ' -f1 < <(head -n$(($(wc -l < file) / 4)) file; tail -n$(($(wc -l < file) / 4)) file)
/dev/sda
/dev/sdb
/dev/sdg
/dev/sdh