Как получить уникальные вхождения из файла?

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

log: {"deviceInfo":{"DeviceId":"123","device":"Android"}
log: {"deviceInfo":{"device":"Android","DeviceId":"123"}
log: {"deviceInfo":{"device":"Android","DeviceId":"234"}
log: {"deviceInfo":{"device":"iPhone","DeviceId":"323"}
log: {"deviceInfo":{"device":"iPhone","DeviceId":"323"}

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

log: {"deviceInfo":{"DeviceId":"123","device":"Android"}
log: {"deviceInfo":{"device":"Android","DeviceId":"234"}
log: {"deviceInfo":{"device":"iPhone","DeviceId":"323"}

Я попытался использовать awk , но я могу понять, как это понять. Кто-нибудь знает как это сделать?

Я знаю, что должен быть способ просто распечатать DeviceId с помощью awk , но я, похоже, не понял его. Как только я получу DeviceId , я могу просто перейти к sort и uniq .

1
У вашего входа действительно есть недостающая закрывающая фигурная скобка в конце каждой строки?
добавлено автор TLP, источник
Это выглядит как расширенный синтаксис JSON, вы можете использовать библиотеку разбора JSON
добавлено автор Basile Starynkevitch, источник

6 ответы

С GNU awk:

gawk 'match($0, /DeviceId":"([^"]+)/, a) && seen[a[1]]++ == 0' log

Учитывая ваш вход, эти выходы

log: {"deviceInfo":{"DeviceId":"123","device":"Android"}
log: {"deviceInfo":{"device":"Android","DeviceId":"234"}
log: {"deviceInfo":{"device":"iPhone","DeviceId":"323"}

( Заметьте, это, по сути, перевод gawk ответа Perleone , хотя в то время я не заметил )

4
добавлено
благодаря! это помогло!
добавлено автор thunderousNinja, источник

Использовать Perl:

perl -lne 'if ( m{"DeviceId":" ([^"]+) "}xms ) { print if not $seen{$1}++; }' 
4
добавлено
Если кто-то знает, как сделать это с помощью awk ? Я действительно ненавижу perl ...
добавлено автор Zulu, источник
Затем попробуйте cat log | perl ... . Это работает? Есть ли ошибки?
добавлено автор Perleone, источник

С любым awk:

$ awk '{id=$0;gsub(/.*DeviceId":"|".*/,"",id)} !seen[id]++' file
log: {"deviceInfo":{"DeviceId":"123","device":"Android"}
log: {"deviceInfo":{"device":"Android","DeviceId":"234"}
log: {"deviceInfo":{"device":"iPhone","DeviceId":"323"}
1
добавлено

Основываясь на ответе @ cnicutar, используйте sed , sort и cut :

sed 's/.*\"DeviceId":"\([0-9]*\).*/\1\t\0/'  | sort -u -k 1,1 | cut -f 2

Вывод:

log: {"deviceInfo":{"DeviceId":"123","device":"Android"}
log: {"deviceInfo":{"device":"Android","DeviceId":"234"}
log: {"deviceInfo":{"device":"iPhone","DeviceId":"323"}
1
добавлено

Уникальные идентификаторы устройств с использованием awk :

$ awk '/DeviceId/&&!a[$1]++&&gsub(/[^[:digit:]]/,"")' RS='[{,}]' file
123
234
323

Хорошая вещь с awk - это ассоциативные массивы, не нужно переводить в sort -u .

1
добавлено

Лучше разобрать JSON (но еще один быстрый awk):

awk -F'.*DeviceId":"|["}]' '!A[$2]++' file 

Применяя предложение Эд Мортона о том, чтобы слить еще 3 персонажа:

awk -F'.*DeviceId":"|"' '!A[$2]++' file 
1
добавлено
+1 Хорошее решение, я бы подумал об этом! Вы можете сбрить пару символов, выполнив | вместо | ["}] , если хотите.
добавлено автор Ed Morton, источник
Спасибо :) Хорошая идея, действительно, 3 персонажа не нужны
добавлено автор Scrutinizer, источник
Linux Help
Linux Help
2 686 участник(ов)

Правила: https://telegra.ph/Pravila-Linux-Help-10-15

Linux Security
Linux Security
652 участник(ов)

Данная группа принципиально про безопасность и в частности про безопасность Linux. Прочие темы просим обсуждать в профильных чатах.

Modern::Perl
Modern::Perl
362 участник(ов)

Пожалуйста, представьтесь при добавлении в группу. Это необходимо во избежание спам-ботов. Ваше первое сообщение не должно быть ссылкой или репостом. Мы всегда рады нестандартным вопросам.

use Perl or die;
use Perl or die;
164 участник(ов)

Группа о языке Perl и обо всём что с ним связано.

pro.bash
pro.bash
123 участник(ов)

All about Nix shells, signals, processes and development in general.

Linux Gaming RUS
Linux Gaming RUS
28 участник(ов)

Русскоязычный чатик, посвящённый играм на различных дистрибутивах Linux, а также wine, proton Arch Linux RU @ArchLinuxChatRU Gnome RU @gnome_ru

pro.perl
pro.perl
22 участник(ов)

Язык программирования Perl