Eu já sei o que partes deste comando fazem:
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
Peça por peça:
1) zgrep
é usado para grep
(pesquisar) .json.gz
arquivos
2) zgrep -v "org" /path/to/files/*
significa encontrar entradas em cada arquivo /path/to/files/*
que não contenham "org"
.
3) |
é um cano; significa "e então"
4) zgrep "FollowEvent"
significa encontrar a string "FollowEvent"
dentro dos resultados encontrados no primeiro zgrep.
5) |
é um cano; significa "e então"
6) zgrep -o 'login":"[^"]*"'
significa encontrar correspondências não vazias para a string login":"
e todo o texto após a palavra `login' na entrada.
7) | cut -d'"' -f3
significa “e então pegar apenas o terceiro campo da correspondência resultante”, que é, neste caso, um nome de usuário.
8) | sort | uniq -c
significa "e então classificar os nomes de usuário e contar o número de instâncias exclusivas de cada nome de usuário".
Até agora, temos:
zgrep -v "org" /path/to/files/* | zgrep "FollowEvent" | zgrep -o 'login":"[^"]*"' | cut -d'"' -f3 | sort | uniq -c
que é encontrar, em todas as entradas em todos os arquivos em /path/to/files/* que não contêm a string "org", mas contêm a string "FollowEvent", todos os nomes de usuário (que é o texto no terceiro campo após " login") e, em seguida, classificar esses nomes de usuário e contar o número de vezes que cada nome de usuário aparece.
Meu problema é com esta parte:
sed '1i{ s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/;$a}'
Eu sei (ou acho que sei) isto:
1) sed
é um editor de stream que permite a manipulação de texto.
2) sed '1i{
significa "na linha anterior, insira {"
3) No total, este comando retorna {"username":count of that username}
para todos os nomes de usuário em todos os arquivos, conforme discutido anteriormente. Em seguida, ele os coloca em um arquivo chamado usernames_followevents.txt
.
4) A parte "\2":
significa "coloque aspas duplas ao redor do nome de usuário, que é o segundo campo (?) e depois insira:".
Gostaria de manipular o sed
comando, mas sem entender o resto dos detalhes não posso começar a fazer modificações.
Alguém poderia explicar o que cada parte do sed
comando está fazendo?
Responder1
A maneira como o comando sed está escrito agora está incorreta. Deve ser um script como este:
1i{
s/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/
$a}
ou em uma única linha como esta:
sed -e '1i{' -e 's/\s*\([0-9]*\)\s*\(.*\)/"\2": \1,/' -e '$a}'
Literalmente tudo o que você coloca após os comandos i
e a
até uma nova linha ou final de expressão (com -e) é impresso diretamente na saída padrão.
Quanto ao que faz, vamos decompô-lo:
1i{
1
é um endereço de linha. Diz ao sed quando executar um comando. Quando o conteúdo da primeira linha é lido no espaço padrão (sem a nova linha final), ele i
insere '{' na saída padrão em uma linha separada. Observe que o espaço padrão permanece inalterado, não foi adicionado '{' a ele.
s
é o comando de busca e substituição, o comando mais versátil do sed. \s
corresponde a um espaço em branco. \(regex\)
está agrupando o regex dentro dele como em matemática, mas também armazena o que foi correspondido por ele em um registro numérico baseado na ordem desse grupo: \1 a \9.
A saída de uniq -c
é algo assim:
occurrences string
3 user
Agora a parte complicada:
\s*\([0-9]*\)\s*\(.*\)
Ainda na linha 1. O espaço padrão é um monte de espaços, depois '3 usuários'. Para corresponder a isso, procuramos o espaço em branco zero ou mais vezes, depois um dígito muitas vezes, que é um número (na minha opinião deveria ter sido + em vez de *) que está armazenado no registro \1, então o espaço (* é não é necessário, eu acho), então qualquer caractere muitas vezes (novamente + teria sido melhor) que está armazenado no registro \2. Então agora, a ocorrência está em \1 e string/user em \2.
"\2": \1,
A linha inteira foi correspondida e as partes foram armazenadas, agora substituímos o que foi correspondido por aspas, depois usuário, depois aspas, dois pontos, espaço, ocorrência e vírgula.
$a}
$
também é um endereço de linha. Se a linha atual for a última, no momento não, chame o a
comando para anexar '}' à saída padrão em uma linha separada.
Este é o fim do processamento do código para esta linha, a impressão automática do espaço do padrão tal como está após a manipulação ser feita, então o conteúdo da segunda linha é lido e todo o ciclo se repete.
Exemplo de saída:
{
"user": 3,
}
Esse é basicamente um formato de arquivo JSON, embora indentado incorretamente.
É isso. Desculpe por escrever romances :)