uniq только частью линии - PullRequest
       82

uniq только частью линии

0 голосов
/ 01 марта 2019

Я пытаюсь объединить список адресов электронной почты, но я хочу uniq (или uniq -i -u) по адресу электронной почты, а не по всей строке, чтобы у нас не было дубликатов.

список 1:

Company A <companya@companya.com>
Company B <companyb@companyb.com>
Company C <companyc@companyc.com>

список 2:

firstname lastname <firstname@gmail.com>
Fake Person <companyb@companyb.com>
Joe lastnanme <joe@gmail.com>

токовый выход

Company A <companya@companya.com>
Company B <companyb@companyb.com>
Company C <companyc@companyc.com>
firstname lastname <firstname@gmail.com>
Fake Person <companyb@companyb.com>
Joe lastnanme <joe@gmail.com>

желаемый выход будет

Company A <companya@companya.com>
Company B <companyb@companyb.com>
Company C <companyc@companyc.com>
firstname lastname <firstname@gmail.com>
Joe lastnanme <joe@gmail.com>

(поскольку companyb@companyb.com указан в обоих)

Как я могу это сделать?

Ответы [ 5 ]

0 голосов
/ 01 марта 2019

Возможно, я не понимаю вопроса!
, но вы можете попробовать это awk:

awk 'NR!=FNR && $3 in a{next}{a[$3]}1' list1 list2
0 голосов
/ 01 марта 2019

с учетом формата вашего файла

$ awk -F'[<>]' '!a[$2]++' files

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

$ awk '!a[$NF]++' files

То же самое можно сделать и с sort

$ sort -t'<' -k2,2 -u files

побочным эффектом является то, что вывод будет отсортирован по желанию (или нет).

NB Для обеих альтернатив предполагается, что угловые скобки не появляются нигде, кроме упаковщиков электронной почты.

0 голосов
/ 01 марта 2019

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

awk '
{
   match($0,/<.*>/)
   val=substr($0,RSTART,RLENGTH)
}
FNR==NR{
   a[val]=$0
   print
   next
}
!(val in a)
' list1 list2

Объяснение: Добавление пояснения к вышеуказанному коду.

awk '                                    ##Starting awk program here.
{                                        ##Starting BLOCK which will be executed for both of the Input_files.
   match($0,/<.*>/)                      ##Using match function of awk where giving regex to match everything from < to till >
   val=substr($0,RSTART,RLENGTH)         ##Creating variable named val whose value is substring of current line starting from RSTART to value of RLENGTH, basically matched string.
}                                        ##Closing above BLOCK here.
FNR==NR{                                 ##Checking condition FNR==NR which will be TRUE when 1st Input_file named list1 will be read.
   a[val]=$0                             ##Creating an array named a whose index is val and value is current line.
   print $0                              ##Printing current line here.
   next                                  ##next will skip all further statements from here.
}
!(val in a)                              ##Checking condition if variable val is NOT present in array a if it is NOT present then do printing of current line.
' list1 list2                            ##Mentioning Input_file names here.

Вывод будетследующим образом.

Company A <companya@companya.com>
Company B <companyb@companyb.com>
Company C <companyc@companyc.com>
firstname lastname <firstname@gmail.com>
Joe lastnanme <joe@gmail.com>
0 голосов
/ 01 марта 2019

uniq имеет опцию -f, чтобы игнорировать количество полей, разделенных пробелами, поэтому мы можем отсортировать по третьему полю и затем игнорировать первые два:

$ sort -k 3,3 infile | uniq -f 2
Company A <companya@companya.com>
Company B <companyb@companyb.com>
Company C <companyc@companyc.com>
firstname lastname <firstname@gmail.com>
Joe lastnanme <joe@gmail.com>

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

ПроверкаОтвет karakfa, чтобы увидеть, как uniq здесь даже не требуется.

В качестве альтернативы, просто проверяя уникальность последнего поля:

awk '!e[$NF] {print; ++e[$NF]}' infile

или даже корочеКража из каракфа, awk '!e[$NF]++' infile

0 голосов
/ 01 марта 2019

Вот один в awk:

$ awk '
match($0,/[a-z0-9.]+@[a-z.]+/) {      # look for emailish string *
    a[substr($0,RSTART,RLENGTH)]=$0   # and hash the record using the address as key
}
END {                                 # after all are processed
    for(i in a)                       # output them in no particular order
        print a[i]
}' file2 file1                        # switch order to see how it affects output

Вывод

Company A <companya@companya.com>
Company B <companyb@companyb.com>
Company C <companyc@companyc.com>
Joe lastnanme <joe@gmail.com>
firstname lastname <firstname@gmail.com>

Скрипт ищет очень простую строку электронной почты (* посмотрите регулярное выражение в скрипте и настройте его по своему вкусу)который используется для хеширования целых записей, последний экземпляр выигрывает, так как предыдущий перезаписывается.

...