#grep
#grep
Вопрос:
У меня есть набор из многих .json.gz
файлов. В каждом файле есть записи, подобные этой:
{"type":"e1","public":true, "login":"username1", "org":{"dict","of":"lots_of_things"}}
{"type":"e2","public":true, "login":"username2"}
Независимо от того, где в каждом вложенном dict появляется «login», я хочу иметь возможность обнаруживать его и принимать имя пользователя, только если ключ «org» нигде не существует во вложенном dict. Я также хочу подсчитать, сколько раз каждое имя пользователя появляется в файлах.
Моим конечным результатом должен быть файл dicts, который выглядит следующим образом:
{'username2: 1}
потому что, конечно, username1 не будет учитываться: ключ «org» появляется в его dict.
Я ищу что-то вроде:
zgrep -Rv "org" . | zgrep -o 'login":"[^"]*"' /path/to/files/* | cut -d'"' -f3 | sort | uniq -c | sed '1i{
s/s*([0-9]*)s*(.*)/"2": 1,/;$a}' > outputfile.txt
Я не уверен в этой части:
zgrep -Rv "org" . |
Остальные успешно создают тип файла, который я ищу. Я просто не уверен в порядке операций здесь.
Редактировать
Я должен был быть более ясным, я прошу прощения. Также часто существует несколько экземпляров ключа «login» для каждого основного объекта dict. Например (используя «k» для любого ключа, который не является login и не org, и используя «v» для значения):
{"k":"v","k":{"k":{"k":"v","login":"username1"},"k":"v"},"k":{"k":"v","login":"username2"}}
{"k":{"k":"v","k":"v"},"k":{"org":{"k":"v","k":v,"login":"username3"},"k":"v"},"k":{"k":"v","login":"username4"}}
{"k":{"k":"v"},"k":{"k":{"k":"v","login":"username1"},"login":"username2"}}
Поскольку ключ org
появляется во втором дикте, я хочу исключить имена пользователей 3 и 4 из дикта, который я создаю, и сохранить в файл.
Например, я хочу, чтобы это было в файле:
{'username1': 2}
{'username2': 2}
Комментарии:
1. Вы пробовали анализировать JSON с помощью синтаксического анализатора, такого как
jq
? Также можете ли вы предоставить действительный образец JSON, чтобы я мог порекомендовать способ использованияjq
для него2. Дело в том, что они на самом деле не являются допустимыми файлами json, насколько я понимаю. Формат соответствует тому, который я дал. Чтобы быть допустимым json, я думаю, у меня не может быть вложенных dicts, но это то, что у меня есть.
Ответ №1:
Решение AWK и замена find -R на более надежный find:
find . -type f -name "*.json.gz" -print0 | xargs -0 zgrep -v -h '"org"' | awk '{ if ( match($0,/"login":"[^"] "/) ) logins[substr($0,RSTART 8,RLENGTH-8)] ; } END { for ( i in logins ) print("{" i ":" logins[i] "}"); }'
Пример вывода:
{"username2":1}
Ответ №2:
не grep, а задание gnu sed со сценарием, ваши данные в ‘a’
i=
for e in $(sed -nE '/.*borgb.*/!s/.*"login":"(w )".*/{1:}/p' a)
{
let i ;echo ${e/:/:$i}
}
используйте ‘>’ в конце для сохранения в файле
если установлено лучшее регулярное выражение: ‘pcregrep’, оно также работает;
pcregrep -io '(?!.*borgb.*)(?<="login":")w (?=".*)' a
замените приведенный выше сценарий sed … на немного скорректированную распечатку
Ответ №3:
Это сработало:
zgrep -v "org" *.json.gz | zgrep -o 'login":"[^"]*"' | cut -d'"' -f3 | sort | uniq -c | sed '1i{
s/s*([0-9]*)s*(.*)/"2": 1,/;$a}' > usernames_2011.txt