Сравните первые пять элементов столбца с остальными

Остерегайтесь этого, запустив

logrotate -vdf /etc/logrotate.conf

событие, хотя и смоделированное, будет зарегистрировано в /var/lib/logrotate.statusи последующие запуски logrotate ответят упомянутым

log does not need rotating
0
30.07.2019, 14:17
2 ответа

Обычно лучше работать со строками (строками ). Такие инструменты, как awk, работают с одной строкой за раз. Чтобы преобразовать ваши столбцы в строки (, то есть транспонировать ), используйте GNUdatamash. Затем awkможет сделать правильные тесты для каждой строки отдельно, печатать ее или нет. В конце снова используйте datamash, чтобы преобразовать результат в исходный формат :

.
<data datamash transpose | awk '{
    for (i=2; i<=5; i++) if ($1!=$i) next
    for (i=6; i<=NF; i++) if ($1==$i) next
    print
}' | datamash transpose

Объяснение логики:

  • Первый forпропускает строку и начинает сначала, если какое-либо из полей 2..5 отличается от номера поля 1. Все 5 полей равны, это единственная возможность, которая позволяет программе перейти к следующей строке кода.
  • Второй forпропускает строку и начинает сначала, если любое из следующих полей совпадает с первым.
  • Если программа вышла за пределы обоих fors, то это означает, что никакого противоречия вашим критериям обнаружено не было. Только тогда печатается вся строка.

Примечания:

  • В исходной задаче (без транспонирования )вам нужно прочитать следующую строку, только если есть хотя бы один столбец, который еще не противоречит вашим критериям. В зависимости от данных возможно, что все столбцы могут быть объявлены несоответствующими -сразу после чтения нескольких первых строк. В таком случае алгоритм может быстро выйти и вообще ничего не напечатать. Но datamash transposeнеобходимо прочитать и обработать весь файл (или поток )независимо от данных. В этом контексте мое решение неоптимально.
  • На случай, если datamashнедоступен, есть awkрешение здесь .
2
28.01.2020, 02:29

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

ХТН.

rs -T  inp |
perl -lane 'print if "@F" =~ /^(\S+)(?: \1){4}(?: (?:(?!\1(?=(?: |$))).)+)+$/' |
rs -T

Выход:

Jhon    Ben     Tom
Jhon    Ben     Tom
Jhon    Ben     Tom
Jhon    Ben     Tom
Jhon    Ben     Tom
Dave    Taylor  Sara
Dave    Harvey  Sara
0
28.01.2020, 02:29

Теги

Похожие вопросы