Вопрос или проблема
Я начинающий в 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
.
Компоненты
-
awk: это мощная утилита для обработки текстов и извлечения данных в Unix-системах, которая позволяет выполнять широкий спектр задач, начиная с простого фильтра и заканчивая сложной обработкой структурированных данных.
-
sort: предназначена для сортировки строк текста в файле. Она может сортировать целые числа, строки и даже настраивать порядок сортировки с использованием различной конфигурации, такой как указание разделителя.
-
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
предоставит вам доступ к глубинной манипуляции данными, что значительно расширит ваши аналитические возможности. Рекомендуется экспериментировать с приведёнными примерами, чтобы лучше понять, как происходят сортировка и фильтрация данных.