2015-01-14 4 views
0

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

Хотелось бы удалить все записи, которые не имеют уникальности через первые 4 столбца. Так применяя awk сценарий к:

BLUE,CAR,RED,HOUSE,40 
    BLUE,CAR,BLACK,HOUSE,20 
    BLUE,CAR,GREEN,HOUSE,10 
    BLUE,TRUCK,RED,HOUSE,40 
    BLUE,TRUCK,GREEN,HOUSE,40 
    BLUE,TRUCK,RED,HOUSE,40 

Если в результате

BLUE,CAR,RED,HOUSE,40 
    BLUE,CAR,BLACK,HOUSE,20 
    BLUE,CAR,GREEN,HOUSE,10 
    BLUE,TRUCK,GREEN,HOUSE,40 

Я попытался:

awk -F"," -v OFS="," '{cnt[$1,$2,$3,$4]++} END {for (rec in cnt) if (cnt[rec] == 1) print rec}' ss.txt 

успешно удаляет как простофили, но не применяется правильный разделитель или печать всей записи, в результате чего:

BLUECARREDHOUSE 
    BLUETRUCKGREENHOUSE 
    BLUECARBLACKHOUSE 
    BLUECARGREENHOUSE 

Я предпочитаю решение awk, но любое переносное решение приветствуется.

+0

Вы хотите получить дополнительные данные на выходе (40 в первой записи)? –

+0

Да, вся запись должна быть напечатана, даже если дублирующие значения устанавливаются только в первых четырех полях. – mlegge

ответ

3

Учитывая, что вы хотите все записи для записей, которые являются уникальными в первые 4 колонки, это будет делать работу:

awk -F',' '{cnt[$1,$2,$3,$4]++;line[$1,$2,$3,$4] = $0} 
      END {for (rec in cnt) if (cnt[rec] == 1) print line[rec]}' \ 
    ss.txt 

Сохранить линии, а также счетчики; верните то, что вы ввели. Это становится болезненным, если у вас есть файлы гигабайта; есть способы сохранить только уникальные строки, если хотите. Это сохраняет только первую версию каждой строки и удаляет запись, когда она, как известно, не является уникальной. (Непроверенные -.. Но я считаю, что это должно работать Modified на comment от Ed Morton)

awk -F',' '{ if (cnt[$1,$2,$3,$4]++ == 0) 
       line[$1,$2,$3,$4] = $0 
      else 
       delete line[$1,$2,$3,$4] 
      } 
      END {for (rec in line) print line[rec]}' \ 
    ss.txt 

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

awk -F',' '{cnt[$1,$2,$3,$4]++;line[$1,$2,$3,$4] = $1 "," $2 "," $3 "," $4} 
      END {for (rec in cnt) if (cnt[rec] == 1) print line[rec]}' \ 
    ss.txt 
+0

для непроверенного, вам не нужно снова проверять 'cnt', просто сделайте раздел END' END {для строки в строке) [rec]} '' –

+1

@EdMorton: Yup - достаточно. (Строго говоря, все они непроверены, но это был тот, на который я был наименее уверен, другие выглядели хорошо, основываясь на опыте.) И я сжимал ответ между компиляциями. –

+0

FWIW Последнее может быть просто awk BEGIN {FS = SUBSEP = ","} {cnt [$ 1, $ 2, $ 3, $ 4] ++} END {для (rec in cnt) if (cnt [rec] = = 1) print rec} '' –