Как отобразить все строки, в которых в определенном столбце содержатся дублирующиеся значения?

Вопрос или проблема

Я начинающий в Unix, из скрипта Unix ниже:

EmpNo#Email#Name#JobLevel#Experience
641357#Amrit_Mohanty#Amrit Mohanty#3#2
678522#Puneet_Mishra#Puneet Mishra#3#1
670242#Vikas_Bharti#Vikas Bharti#3#1.5
661822#Aravind_Raghavan#Aravind Raghavan#3#1.5
706209#Sankavi.Boopathy#Sankavi Boopathy#3#0.5
706452#Raja.Ravi#Raja Ravi#3#0.5

Мне нужно знать, как получить все строки, в которых в столбце Experience содержатся дублированные значения. Я использую sort -t '#' -k1,5 employee.txt | uniq -d, но это не работает.

Ожидаемый результат приведен ниже:

670242#Vikas_Bharti#Vikas Bharti#3#1.5
661822#Aravind_Raghavan#Aravind Raghavan#3#1.5
706209#Sankavi.Boopathy#Sankavi Boopathy#3#0.5
706452#Raja.Ravi#Raja Ravi#3#0.5

Если вы видите, значение из последнего столбца дублируется. Спасибо за вашу поддержку. Очень признателен

Прочитайте файл дважды, используйте ассоциативный массив с последним полем в качестве ключа для подсчета количества раз, когда вы видели каждое последнее поле, а затем при втором прохождении файла выведите строку, если значение, связанное с последним полем в массиве, больше 1:

$ awk -F'#' 'NR==FNR{a[$NF]++; next} a[$NF]>1' file file
670242#Vikas_Bharti#Vikas Bharti#3#1.5
661822#Aravind_Raghavan#Aravind Raghavan#3#1.5
706209#Sankavi.Boopathy#Sankavi Boopathy#3#0.5
706452#Raja.Ravi#Raja Ravi#3#0.5

Объяснение

  • awk -F'#' запускает awk, используя # в качестве разделителя полей ввода.
  • NR==FNR{a[$NF]++; next}: NR — текущий номер строки, а FNR — текущий номер строки в файле, который в данный момент читается. При передаче более чем одного файла в awk эти две переменные будут равны только при чтении первого файла. Поэтому блок кода будет выполняться только для первого файла. a[$NF]++; next: переменная NF указывает количество полей, поэтому $NF — это значение последнего поля. Мы используем это в качестве ключа в массиве a и увеличиваем связанное значение на единицу. Это подсчитывает количество раз, когда было замечено каждое последнее поле. Команда next переходит к следующей строке, чтобы мы не выполняли оставшуюся часть скрипта для этой строки.
  • a[$NF]>: в awk, когда что-то оценивается как истинное, действие по умолчанию — вывести текущую строку. Поскольку это выполняется только для второго файла (в вашем случае, второй раз, когда мы читаем один и тот же файл) из-за next в блоке NR==FNR, и учитывая, что это будет истинным только если последнее поле было встречено более одного раза при первом проходе, это приводит к выводу тех строк, чье последнее поле было встречено более одного раза.

Если (как кажется) это задание на дом, вероятно, предполагается, что вы решите его, используя базовые утилиты *nix, такие как awk, используя один из методов, показанных здесь:

Однако, если это реальное приложение, это, вероятно, легче всего будет решить, используя методы баз данных, подобные описанным здесь:

Для вашего тривиального примера вы можете использовать csvsql из пакета csvkit на базе Python:

csvsql -y0 -I -d'#' --query '
  SELECT * FROM employee WHERE Experience IN (
    SELECT Experience FROM employee GROUP BY Experience HAVING COUNT(*) > 1
  )
' employee.txt
EmpNo,Email,Name,JobLevel,Experience
670242,Vikas_Bharti,Vikas Bharti,3,1.5
661822,Aravind_Raghavan,Aravind Raghavan,3,1.5
706209,Sankavi.Boopathy,Sankavi Boopathy,3,0.5
706452,Raja.Ravi,Raja Ravi,3,0.5


Одна из проблем вашего подхода ‘sort’ / ‘uniq’ заключается в том, что последний по умолчанию обнаруживает только уникальные (или дублированные) *строки*: хотя GNU реализует опцию `-f` для пропуска начальных полей, которая, по-видимому, жестко запрограммирована для использования разделителей пробелов (т.е. у нее нет аналога `-t` в команде `sort`). Вы можете заменить разделители `#` на пробелы, но вам придется “жонглировать” пробелами, которые уже существуют *внутри* полей. Вам также потребуется `-D`, а не `-d`, для вывода всех дубликатов. Итак, вам нужно будет

  • сортировка по 5-му полю
  • замена вложенных пробелов в полях на другие однозначные символы
  • замена разделителей # на пробелы
  • выбор дубликатов, игнорируя первые 4 (теперь пробел-разделенные) поля
  • замена разделителей пробелов на #
  • обратная замена вложенных символов

например:

sort -t’#’ -nk5 employee.txt | tr ‘ #’ ‘@ ‘ | uniq -f4 -D | tr ‘ @’ ‘# ‘

Ответ или решение

Теория

Работа с файлами в формате CSV (Comma-Separated Values) может быть важной задачей при обработке данных в Unix-подобных системах. Одной из частых задач является поиск строк, где значения в определённой колонке повторяются. Понимание того, как обращаться с такими случаями, поможет вам эффективно фильтровать и анализировать данные. Для решения этой задачи полезно использовать утилиты командной строки, такие как awk, sort, и uniq.

Компоненты

  1. awk: это мощная утилита для обработки текстов и извлечения данных в Unix-системах, которая позволяет выполнять широкий спектр задач, начиная с простого фильтра и заканчивая сложной обработкой структурированных данных.

  2. sort: предназначена для сортировки строк текста в файле. Она может сортировать целые числа, строки и даже настраивать порядок сортировки с использованием различной конфигурации, такой как указание разделителя.

  3. uniq: выполняет задачу удаления дубликатов строк. Однако, uniq работает только с соседними строками, поэтому необходимо предварительно выполнить сортировку данных.

Пример

Для понимания обрабатываем данные следующего вида:

EmpNo#Email#Name#JobLevel#Experience
641357#Amrit_Mohanty#Amrit Mohanty#3#2
678522#Puneet_Mishra#Puneet Mishra#3#1
670242#Vikas_Bharti#Vikas Bharti#3#1.5
661822#Aravind_Raghavan#Aravind Raghavan#3#1.5
706209#Sankavi.Boopathy#Sankavi Boopathy#3#0.5
706452#Raja.Ravi#Raja Ravi#3#0.5

Задача в том, чтобы вывести все строки, где последний столбец Experience содержит повторяющиеся значения. В данном случае ожидаемый результат:

670242#Vikas_Bharti#Vikas Bharti#3#1.5
661822#Aravind_Raghavan#Aravind Raghavan#3#1.5
706209#Sankavi.Boopathy#Sankavi Boopathy#3#0.5
706452#Raja.Ravi#Raja Ravi#3#0.5

Применение

Метод с awk

awk позволяет обрабатывать данные путем создания массивов и фильтрации строк по различным критериям. Вот как можно применить awk для нашего случая:

awk -F'#' 'NR==FNR{a[$NF]++; next} a[$NF]>1' файл файл

Пояснение:

  • -F'#': Устанавливает символ # как разделитель полей.
  • NR==FNR{a[$NF]++; next}: Читает файл первый раз, увеличивая счетчик в массиве a для каждого последнего поля $NF (то есть для поля Experience), но не выполняет никаких действий с этими строками на текущем шаге.
  • a[$NF]>1: Во время второго обхода печатает строки, если значение последнего поля встречалось в первом проходе более одного раза.

Альтернативный подход с sort и uniq

Утилиты sort и uniq совместно могут решить эту задачу, но требуют немного более сложной манипуляции с данными из-за особенностей работы uniq.

sort -t'#' -nk5 файл | uniq -f4 -D

Пояснение:

  • -t'#': Указывает sort, что столбцы в строках разделены символом #.
  • -nk5: Сортирует данные по пятому столбцу (опыт работы).
  • uniq -f4 -D: -f4 пропускает первые четыре столбца при проверке на уникальность, а -D выводит все найденные дубликаты.

Библиотеки и пакеты

Если задача решается в более широком контексте с большими объемами данных, имеет смысл рассмотреть использование специализированных библиотек или рамок, таких как Python с его библиотеками для обработки данных (pandas, например), или даже использовать csvsql из пакета csvkit для обработки CSV-файлов с помощью SQL-запросов.

Пример использования csvsql:

csvsql -y0 -I -d'#' --query '
  SELECT * FROM employee WHERE Experience IN (
    SELECT Experience FROM employee GROUP BY Experience HAVING COUNT(*) > 1
  )
' employee.txt

Этот запрос позволит вам использовать свободу SQL для фильтрации данных на основе дублирующихся значений в столбце Experience.

Заключение

Обработка и извлечение информации из файлов, содержащих структурированные данные в текстовом формате, является важной задачей при работе с большими объемами данных. Особенно важным является умение использовать набор стандартных утилит Unix для выполнения таких операций. Освоение awk, sort и uniq предоставит вам доступ к глубинной манипуляции данными, что значительно расширит ваши аналитические возможности. Рекомендуется экспериментировать с приведёнными примерами, чтобы лучше понять, как происходят сортировка и фильтрация данных.

Оцените материал
Добавить комментарий

Капча загружается...