Как отсортировать уникальные данные по конкретному столбцу и напечатать первую уникальную 3-значную цифру и добавить значение второго столбца - PullRequest
0 голосов
/ 28 апреля 2019

File.txt

chocolate,Paris,ER
milkchocolat,France,FR
berriesnoire,Paris,FR
chocolatewhite,Paris,FR
darkchocolat,Italy,IL
orange,usa,USA
plume,Paris,FR
milkshake,France,FR
orangebark,usa,USA

Желание выхода:

ber,Paris
cho,Paris
dar,Italy
mil,France
ora,usa
plu,paris

cat file.txt | awk -F”,” ‘{print $1”,”$2}’ | cut -c-3 | sort -u

Эта команда дает мне только один столбец в выводе

Токовый выход:

ber
cho
dar
mil
ora
plu

Ответы [ 4 ]

3 голосов
/ 28 апреля 2019

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

awk 'BEGIN{FS=OFS=","} !seen[key=substr($1,1,3)]++{print key,$2}' file | sort

Учитывая ваш пример ввода, вывод выглядит следующим образом:

ber,Paris
cho,Paris
dar,Italy
mil,France
ora,usa
plu,Paris

Или с любым sed и сортировкой:

sed 's/\(...\)[^,]*\(,[^,]*\).*/\1\2/' file | sort -u

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

Для такого ввода:

chocolate,Paris
chocolate,paris

Первый вывод будет:

cho,Paris

но вывод второго будет:

cho,Paris
cho,paris

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

3 голосов
/ 28 апреля 2019

Вот мой:

awk -F, '{printf "%.3s,%s\n", $1, $2}' data.txt | sort -u
3 голосов
/ 28 апреля 2019

С GNU sed и сортировкой:

sed -E 's/(...)[^,]*/\1/; s/,[^,]*$//' File.txt | sort -u

Вывод:

ber,Paris
cho,Paris
dar,Italy
mil,France
ora,usa
plu,Paris

См .: 5.7 Обратные ссылки и Subexpressions

1 голос
/ 29 апреля 2019

Простой awk | sort решение:

$ time awk -F, -v OFS=, '{ print substr($1, 1, 3), $2 }' file | sort -u
ber,Paris
cho,Paris
dar,Italy
mil,France
ora,usa
plu,Paris

real    0m0.007s
user    0m0.003s
sys     0m0.006s

Я думал, что было бы быстрее сохранить IO, выполнив -u часть в awk , но этолибо эквивалентный, либо чуть медленнее:

$ time awk -F, -v OFS=, -v SUBSEP=, '
    BEGIN { split("", a) }
          { a[substr($1, 1, 3), $2] = "" }
    END   { for (i in a) print i }
' file | sort
ber,Paris
cho,Paris
dar,Italy
mil,France
ora,usa
plu,Paris

real    0m0.007s
user    0m0.006s
sys     0m0.004s

Но немного быстрее отказаться от канала и выполнить все это в версии awk , которая имеет реализацию asorti():

$ time gawk -F, -v OFS=, -v SUBSEP=, '
    BEGIN { split("", a) }
          { a[substr($1, 1, 3), $2] = "" }
    END   { N = asorti(a); for (i=1; i<=N; ++i) print a[i] }
' file
ber,Paris
cho,Paris
dar,Italy
mil,France
ora,usa
plu,Paris

real    0m0.006s
user    0m0.000s
sys     0m0.006s

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

Примечания:

  • Для чего оно стоит, я сравнил mawk 1.3.3 и gawk 4.2.1 на первых двух решениях и gawk последовательно бьют mawk за время для этих случаев.)
  • Я также рассчитал вывод по конвейеру на /dev/null, результаты каждой реализации относительно друг друга были похожи.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...