Я уже знаю, что делают некоторые части этой команды:
zgrep -v "org" /path/to/files/* | zgrep "FollowEvent" | zgrep -o 'login":"[^"]*"' | cut -d'"' -f3 | sort | uniq -c | sed '1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}' > usernames_followevents.txt
Кусок за куском:
1) zgrep
используется для grep
(поиска) в .json.gz
файлах
2) zgrep -v "org" /path/to/files/*
означает поиск записей в каждом файле, /path/to/files/*
которые не содержат "org"
.
3) |
— трубка; означает «и затем»
4) zgrep "FollowEvent"
означает поиск строки "FollowEvent"
среди найденных результатов первого zgrep.
5) |
— трубка; означает «и затем»
6) zgrep -o 'login":"[^"]*"'
означает поиск непустых совпадений для строки login":"
и всего текста после слова «login» в записи.
7) | cut -d'"' -f3
означает «а затем взять только третье поле из полученного совпадения», которое в данном случае является именем пользователя.
8) | sort | uniq -c
означает «а затем отсортировать имена пользователей, а затем подсчитать количество уникальных вхождений каждого имени пользователя».
На данный момент мы имеем:
zgrep -v "org" /path/to/files/* | zgrep "FollowEvent" | zgrep -o 'login":"[^"]*"' | cut -d'"' -f3 | sort | uniq -c
который находит во всех записях во всех файлах в /path/to/files/*, которые не содержат строку "org", но содержат строку "FollowEvent", все имена пользователей (которые представляют собой текст в третьем поле после "login"), а затем сортирует эти имена пользователей и подсчитывает количество появлений каждого имени пользователя.
У меня проблема вот с этой частью:
sed '1i{ s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}'
Я знаю (или думаю, что знаю) следующее:
1) sed
— потоковый редактор, позволяющий манипулировать текстом.
2) sed '1i{
означает «в предыдущей строке вставить {»
3) В целом эта команда возвращает {"username":count of that username}
все имена пользователей во всех файлах, как обсуждалось ранее. Затем она помещает их в файл с именем usernames_followevents.txt
.
4) Часть "\2":
означает «заключите имя пользователя, которое является вторым полем (?), в двойные кавычки, а затем вставьте :».
Я хотел бы изменить sed
команду, но, не понимая остальных деталей, я не могу начать вносить изменения.
Может ли кто-нибудь объяснить, что sed
делает каждая часть команды?
решение1
То, как сейчас написана команда sed, неправильно. Это должен быть либо скрипт вроде этого:
1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/
$a}
или в одну строку, например так:
sed -e '1i{' -e 's/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/' -e '$a}'
Буквально все, что вы помещаете после команд i
и a
до новой строки или конца выражения (с -e), напрямую выводится на стандартный вывод.
Давайте разберемся, что он делает:
1i{
1
— это адрес строки. Он сообщает sed, когда выполнять команду. Когда содержимое первой строки считывается в пространство шаблона (без завершающего символа новой строки), он i
вставляет '{' в стандартный вывод на отдельной строке. Обратите внимание, что пространство шаблона не изменилось, он не добавил '{' в него.
s
— команда поиска и замены, самая универсальная команда в sed. \s
Соответствует пробелу. \(regex\)
Группирует внутри себя регулярное выражение, как в математике, но также сохраняет то, что совпало, в числовом регистре на основе порядка этой группы: от \1 до \9.
Вывод uniq -c
примерно такой:
occurrences string
3 user
А теперь сложная часть:
\s*\([0-9]*\)\s*\(.*\)
Все еще на строке 1. Шаблонное пространство — это куча пробелов, затем «3 user». Чтобы сопоставить это, мы ищем пробел ноль или более раз, затем цифру много раз, то есть число (по моему мнению, это должно было быть + вместо *), которое хранится в регистре \1, затем пробел (*, я думаю, не нужен), затем любой символ много раз (опять же, лучше было бы +), который хранится в регистре \2. Так что теперь вхождение находится в \1, а строка/пользователь в \2.
"\2": \1,
Вся строка была сопоставлена, а ее части сохранены, теперь мы заменяем то, что было сопоставлено, на кавычки, затем пользователя, затем кавычки, двоеточие, пробел, вхождение и запятую.
$a}
$
также является адресом строки. Если текущая строка последняя, в данный момент нет, вызовите a
команду для добавления '}' к стандартному выводу на отдельной строке.
На этом обработка кода для данной строки заканчивается, происходит автоматическая печать пространства шаблона в том виде, в котором оно есть после выполнения манипуляции, затем считывается содержимое второй строки и весь цикл повторяется.
Пример вывода:
{
"user": 3,
}
По сути, это формат файла JSON, хотя и с неправильными отступами.
Вот и все. Извините за написание романов :)