Существует ли путь к 'uniq' столбцом?

У меня есть .csv файл как это:

stack2@example.com,2009-11-27 01:05:47.893000000,example.net,127.0.0.1
overflow@example.com,2009-11-27 00:58:29.793000000,example.net,255.255.255.0
overflow@example.com,2009-11-27 00:58:29.646465785,example.net,256.255.255.0
...

Я должен удалить дублирующиеся электронные письма (вся строка) из файла (т.е. одна из строк, содержащих overflow@example.com в вышеупомянутом примере). Как я использую uniq только на поле 1 (разделенный запятыми)? Согласно man, uniq не имеет опций для столбцов.

Я попробовал что-то sort | uniq но это не работает.

176
задан Dukeling 17 November 2014 в 13:49
поделиться

5 ответов

sort -u -t, -k1,1 file
  • -u для уникального
  • -t, , поэтому запятая является разделителем
  • -k1,1 для ключевого поля 1

Результат теста:

overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 
302
ответ дан 23 November 2019 в 20:22
поделиться
awk -F"," '!_[$1]++' file
  • -F устанавливает разделитель полей.
  • $ 1 - это первое поле.
  • _ [val] ищет val в хэше _ (обычная переменная).
  • ++ приращение и возвращает старое значение.
  • ! возвращает логическое «нет».
  • в конце есть неявная печать.
96
ответ дан 23 November 2019 в 20:22
поделиться

или если вы хотите использовать uniq:

дает:

1 01:05:47.893000000 2009-11-27 tack2@domain.com
2 00:58:29.793000000 2009-11-27 overflow@domain2.com
1
9
ответ дан 23 November 2019 в 20:22
поделиться

ну, проще, чем изолировать папку столбец с awk, если вам нужно удалить все с определенным значением для данного файла, почему бы просто не выполнить grep -v:

например, чтобы удалить все со значением "col2" во втором месте строка: col1, col2, col3, col4

grep -v ',col2,' file > file_minus_offending_lines

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

awk, чтобы изолировать проблемный столбец: например

awk -F, '{print $2 "|" $line}'

-F устанавливает поле, разделенное на ",", $ 2 означает столбец 2, за которым следует некоторый настраиваемый разделитель, а затем вся строка. Затем вы можете отфильтровать, удалив строки, которые начинаются с оскорбительного значения:

 awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE

, а затем удалите материал перед разделителем:

awk -F, '{print $2 "|" $line}' | grep -v ^BAD_VALUE | sed 's/.*|//g'

(обратите внимание: команда sed небрежна, потому что она не включает экранирование значений.Также шаблон sed действительно должен быть чем-то вроде "[^ |] +" (то есть чем угодно, кроме разделителя). Но, надеюсь, это достаточно ясно.

-3
ответ дан 23 November 2019 в 20:22
поделиться

Сначала отсортировав файл с помощью sort , вы можете применить uniq .

Похоже, файл сортируется отлично:

$ cat test.csv
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

$ sort test.csv | uniq
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
overflow@domain2.com,2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

] Вы также можете использовать магию AWK:

$ awk -F, '{ lines[$1] = $0 } END { for (l in lines) print lines[l] }' test.csv
stack2@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack4@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
stack3@domain.com,2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1
overflow@domain2.com,2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 
-3
ответ дан 23 November 2019 в 20:22
поделиться
Другие вопросы по тегам:

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