eu tenho uma tabela com colunas. Na primeira coluna, tenho tempo, quando o usuário efetuou login, na segunda coluna, tenho um nome de usuário.
13:15:39 fxs1cia1qulm1lk
13:15:39 fxs1cia1qulm1lk
13:15:39 fxs1cia1qulm1lk
13:15:42 faaaa2aa11111
13:15:49 terd1sfsd11fsdf
13:15:49 terd1sfsd11fsdf
13:15:49 terd1sfsd11fsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:15:59 21erdsf123sdfsdf
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:17:50 abcasbbabadab
13:19:19 fxs1ce1iulmla
13:19:19 fxs1ce1iulmla
13:19:19 fxs1ce1iulmla
13:20:42 faaa2a0a1111
Então, o que devo fazer. Eu deveria fazer uma operação única com essas duas colunas, e se o tempo de login do usuário e o nome do usuário forem iguais, devo dizer que esse usuário efetuou login mais de 3 vezes. Eu escrevi um pequeno roteiro:
log_file=/root/log
temp_file=/root/temp
temp_file2=/root/temp2
cat /dev/null > $temp_file
cat /dev/null > $temp_file2
cat /dev/null > $result_file
cat $log_file | awk '{print $1}' | tail -n 20 > $temp_file
cat $log_file | awk '{print $5}' | tail -n 20 > $temp_file2
for i in `uniq -c $temp_file | awk '{print $1}'`; do
for y in `uniq -c $temp_file2 | awk '{print $2}'`; do
if [ $i -gt 3 ] && [ $y -gt 3 ]; then
s=`uniq -c $temp_file2 | awk '$1 == '$i`
echo "The user $s has logged more than 3 times"
fi
done
done
Por favor, verifique, como você acha, este script está correto? Porque, após a saída do meu script em echo, eu tenho isso:
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
The user 4 21erdsf123sdfsdf
4 abcasbbabadab has logged more than 3 times
Mas eu quero ter uma saída como esta:
The user 4 21erdsf123sdfsdf has logged more than 3 times
The user 4 abcasbbabadab has logged more than 3 times
E isso é tudo. Onde eu cometi um erro? Por favor ajude.
Responder1
Você pode fazer isso de uma maneira muito direta comawk
awk '{ users[$2]++ }
END {
for (user in users)
if (users[user] > 1)
printf "%s logged in %d times\n", user, users[user]
}' < /root.log
Este programa verifica o root.log criando um array associativo (também conhecido como hash) com contagens de cada usuário e, em seguida, imprime aqueles que são maiores que um.
Responder2
Então, o único problema é que ele imprime a mesma saída várias vezes? Por que não apenas passar pelo uniq? Despejar em outro arquivo temporário e executar o uniq nele?
Se não é isso que você está perguntando, tenho algumas observações:
- trabalhar com dados separados por linha no bash/sh geralmente é mais problemático do que vale a pena. A menos que a solução seja óbvia, procure uma linguagem de script onde você não precise mexer no IFS o tempo todo. (Se você não sabe o que é o IFS var, então eu realmente recomendo ficar longe do bash/sh para dados separados por linha.)
- como você já está usando o awk, aposto que você poderia fazer tudo como um script awk.
- Como as linhas com as quais você está preocupado são idênticas, você pode fazer isso
sort logfile | uniq -c
. - Você não está classificando seu arquivo antes do uniq, então o uniq não funcionará se as linhas idênticas não estiverem próximas umas das outras. Por exemplo, se Bob e Joe fizerem login ao mesmo tempo e suas entradas de log forem alternadas.
- sempre há grep -c
- leia sobre o comando sort, especialmente -d, -n, -k e -t
ATUALIZAR
Você está pedindo conselhos sobre scripts de shell ou está procurando uma resposta prática para a questão de como faço para descobrir quem está conectado em 3 ou mais sessões?
conselhos de script:
- Tenho certeza que
$s
contém a string inteira,4 21erdsf123sdfsdf <newline> 4 abcasbbabadab
incluindo uma nova linha. Não consigo entender por quê. - Por que você faz
awk '{print $5}'
? Tentei copiar seus dados de exemplo e executá-losawk '{print $5}'
, mas obtive um monte de novas linhas e nada mais. - Você examinou o conteúdo de
$temp_file
e$temp_file2
para ter certeza de que é o que você espera? - Isso
tail -n 20
me diz que você quer apenas entradas 'recentes' e não se importa com o quão recentes. Isso é verdade? - As
cat /dev/null > $file
linhas são redundantes, basta retirá-las. - Substitua o
cat $logfile
porsort $logfile
- Recue seus loops
Basicamente, esse script não fará o que você deseja e não sei dizer como você pretendia que funcionasse, portanto não posso dar conselhos mais específicos. Desculpe.
prático
- use o script awk de @ greg-tarsa ('desculpas para' e, Greg me heartie, eu não sei o 'link' para um usuário com um espaço em 'seu nome)
- você está falando sobre logins atuais em uma caixa unix? Você já tentou o
who
comando? EGwho | awk '{ print $1}' | sort | uniq -c | sort -d -r
ou olast
comando? - procure a resposta para sua pergunta geral (como faço para descobrir quem está logado muitas vezes) em vez da pergunta mais específica que está bloqueando a solução que você já está tentando implementar (Uniq por duas colunas com duas condições) . Se você estiver mais interessado em praticar seu script de shell, faça sua pergunta de uma forma que diga isso.