обнаружение «дублирующих» записей в файле с разделителями табуляции с помощью команд bash & - PullRequest
0 голосов
/ 11 ноября 2019

У меня есть текстовый файл с разделителями табуляции, который нужно проверить на наличие дубликатов. Макет выглядит примерно так. (Первые записи в файле - это имена столбцов.)
Пример входного файла:

+--------+-----------+--------+------------+-------------+----------+
| First  |   Last    | BookID |   Title    | PublisherID | AuthorID |
+--------+-----------+--------+------------+-------------+----------+
| James  | Joyce     |     37 | Ulysses    |         344 |     1022 |
| Ernest | Hemingway |    733 | Old Man... |         887 |      387 |
| James  | Joyce     |    872 | Dubliners  |         405 |     1022 |
| Name1  | Surname1  |      1 | Title1     |           1 |        1 |
| James  | Joyce     |     37 | Ulysses    |         345 |     1022 |
| Name1  | Surname1  |      1 | Title1     |           2 |        1 |
+--------+-----------+--------+------------+-------------+----------+

Файл может содержать до 500 тыс. Строк. После этого мы проверяем, нет ли дубликатов значений BookID и AuthorID. Так, например, в приведенной выше таблице не может быть двух строк с BookID 37 и AuthorID 1022.

вероятно , но не гарантируется, что автор будет сгруппирован последовательнолиний. Если это не так, и это слишком сложно проверить, я могу с этим смириться. Но в противном случае, если автор тот же, нам нужно знать, есть ли дубликат BookID.

Одна сложность - у нас могут быть дубликаты BookID в файле, но это недопустимая комбинация AuthorID + BookID.

Есть хороший способ проверить это в скрипте bash, может быть, какой-то комбо sed и awk или другое средство для достижения этой цели?

Необработанное содержимое файла, разделенное табуляцией, для сценариев:

First   Last    BookID  Title   PublisherID AuthorID
James   Joyce   37  Ulysses 344 1022
Ernest  Hemingway   733 Old Man...  887 387
James   Joyce   872 Dubliners   405 1022
Name1   Surname1    1   Title1  1   1
James   Joyce   37  Ulysses 345 1022
Name1   Surname1    1   Title1  2   1

Ответы [ 4 ]

2 голосов
/ 11 ноября 2019

текстовый файл, разделенный табуляцией

проверяет, нет ли дубликатов значений BookID и AuthorID

И из ответа @ piotr.wittchen столбцы выглядят какэто:

Первый Последний Название BookID PublisherID AuthorID

Все просто:

  • извлечение столбцов BookID AuthorID столбцов
  • sort
  • проверка на наличие дубликатов

cut -f3,6 input_file.txt | sort | uniq -d

Если у вас есть целые строки, нам нужно немного переупорядочить поля, чтобы uniq съела их:

awk '{print $1,$2,$4,$5,$3,$6}' input_file.txt | sort -k5 -k6 | uniq -d -f4

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

nl -w1 input_file.txt |
awk '{print $1,$2,$3,$5,$6,$4,$7}' input_file.txt | sort -k6 -k7 | uniq -d -f5 |
sort -k1 | cut -f2-
2 голосов
/ 11 ноября 2019

Если вы хотите найти и сосчитать дубликаты, вы можете использовать

awk '{c[$3 " " $6]+=1} END { for (k in c) if (c[k] > 1) print k "->" c[k]}'

, который сохраняет количество комбинаций в ассоциативном массиве, а затем печатает счет, если больше 1

1 голос
/ 11 ноября 2019

Это довольно просто с awk:

$ awk 'BEGIN { FS = "\t" }
       ($3,$6) in seen { printf("Line %d is a duplicate of line %d\n", NR, seen[$3,$6]); next }
       { seen[$3,$6] = NR }' input.tsv

Он сохраняет каждую пару bookid, authorid в хеш-таблице и предупреждает, если эта пара уже существует.

1 голос
/ 11 ноября 2019

Как уже сказал @Cyrus в комментарии, ваши вопросы не совсем понятны, но выглядят интересными, и я попытался понять их и дать решение с несколькими предположениями.

Предполагая, что у нас есть следующее records.txtfile:

First   Last        BookID      Title           PublisherID     AuthorID
James   Joyce       37          Ulysses         344             1022
Ernest  Hemingway   733         Old Man...      887             387
James   Joyce       872         Dubliners       405             1022
Name1   Surname1    1           Title1          1               1
James   Joyce       37          Ulysses         345             1022
Name1   Surname1    1           Title1          2               1

мы собираемся удалить строки, которые дублируют значения BookID (столбец 3) и AuthorID (столбец 6) одновременно. Мы предполагаем, что First, Last name и Title также одинаковы, и мы не должны принимать это во внимание, а PublisherID может быть другим или одинаковым (это не имеет значения). Расположение записей в файле не имеет значения (дублированные строки не должны быть сгруппированы вместе).

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

Ernest  Hemingway   733         Old Man...      887             387
James   Joyce       872         Dubliners       405             1022
James   Joyce       37          Ulysses         344             1022
Name1   Surname1    1           Title1          1               1

Удалены дублированные записи одних и тех же книг одного автора для одного издателя.

Вот мое решение этой проблемы в Bash

#!/usr/bin/env bash

file_name="records.txt"
repeated_books_and_authors_ids=($(cat $file_name | awk '{print $3$6}' | sort | uniq -d))

for i in "${repeated_books_and_authors_ids[@]}"
do
    awk_statment_exclude="$awk_statment_exclude\$3\$6 != $i && "
    awk_statment_include="$awk_statment_include\$3\$6 ~ $i || "
done

awk_statment_exclude=${awk_statment_exclude::-3}
awk_statment_exclude="awk '$awk_statment_exclude {print \$0}'"
not_repeated_records="cat $file_name | $awk_statment_exclude | sed '1d'"
eval $not_repeated_records

awk_statment_include=${awk_statment_include::-3}
awk_statment_include="awk '$awk_statment_include {print \$0}'"
repeated_records_without_duplicates="cat $file_name | $awk_statment_include | sort | awk 'NR % 2 != 0'"
eval $repeated_records_without_duplicates

Это, вероятно, нелучшее возможное решение, но оно работает.

С уважением,

Петр

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...