#1 Le 29/10/2015, à 14:13
- nqrkko
[RESOLU] Bash : Extraire et compter le nombre d'occurences
Bonjour à tous,
Je rencontre actuellement un problème sur une partie d'un script bash. Cette partie a pour but de m'informer des tentatives de connexion SSH fructueuses.
Voici mon fichier d’origine "accepted.txt" (c’est un extrait de mon fichier auth.log).
riri 192.168.1.19
titi 192.168.1.8
titi 192.168.1.8
titi 192.168.1.17
roro 192.168.1.22
roro 192.168.1.22
roro 192.168.1.38
rara 192.168.2.18
Je souhaiterais, à partir de cet extrait, obtenir le résultat suivant :
riri
192.168.1.19 : 1 fois
titi
192.168.1.8 : 1 fois
192.168.1.17 : 1 fois
roro
192.168.1.22 : 2 fois
192.168.1.38 : 1 fois
rara
192.168.2.18 : 1 fois
J'ai commencé à développer mon script mais je bloque complètement. Lorsque je l'exécute, j'obtiens le même résultat que le fichier de départ avec en prime le message d'erreur suivant (au départ) : ./test.sh: 13: ./test.sh: [riri: not found
Mon script est le suivant :
#!/bin/sh
prev_user=""
prev_ip=""
rm ssh-ok.txt
cat accepted.txt | while read ligne ; do
set $(echo $ligne)
user=$(eval echo $1)
ip=$(eval echo $2)
number=$(eval echo $3)
if ["$user" == "$prev_user" && "$ip" == "$prev_ip"]; then
number=$((number+1))
awk '{print $1,$2,$number}' $line >> ssh-ok.txt
else
awk '{print $1,$2}' $line >> ssh-ok.txt
fi
prev_user=$user
prev_ip=$ip
done < accepted.txt
cat ssh-ok.txt
Dans ce script, ne sachant pas comment compter le nombre d’occurrence et l'incrémenter à chaque fois, j'ai inséré la variable "number" et ai modifié mon fichier d'origine en ajoutant "1" à la fin de chaque ligne.
Quelqu'un aurait-il une idée des modifications à apporter pour obtenir le résultat que je souhaites s'il vous plait.
Merci par avance pour votre aide !
Dernière modification par nqrkko (Le 29/10/2015, à 18:24)
Hors ligne
#2 Le 29/10/2015, à 14:49
- Postmortem
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Salut,
Alors déjà, soit on fait :
cat accepted.txt | while read ligne ; do
blabla
done
Soit :
while read ligne ; do
blabla
done < accepted.txt
==========================================
Plutôt que :
while read ligne ; do
set $(echo $ligne)
user=$(eval echo $1)
ip=$(eval echo $2)
number=$(eval echo $3)
...
Fait directement :
while read user ip; do
...
done < accepted.txt
(le « number=$(eval echo $3) » ne sert à rien dans ton script, il n'y a que 2 champs sur chaque ligne dans le fichier d'origine)
==========================================
Pour les tests, il faut des espaces en plus et « && » n'est pas accepté entre simple crochets (mais ça l'est entre les doubles); donc soit :
if [ "$user" == "$prev_user" -a "$ip" == "$prev_ip" ]
Soit :
if [[ $user == $prev_user && $ip == $prev_ip ]]
(la suppression des doubles quotes est volontaire dans la 2ème proposition, ils sont inutiles, la variable n'est pas "découpée" entre double-crochets)
==========================================
Et pour info, on ne fait pas ce genre de chose :
ip=$(eval echo $2)
Mais simplement :
ip=$2
Edit :
Le titre de la discussion est « Bash : ... » ; pourquoi commences tu donc ton script par « #!/bin/sh » ??? Si tu veux du bash, il faut mettre « #!/bin/bash ».
Re-edit : sinon, un petit (g)awk :
awk '{ nb[$1][$2]++ } END{ for (i in nb) { printf "%s\n", i; for (j in nb[i]) printf "%s : %s fois\n", j, nb[i][j] }}' accepted.txt
Dernière modification par Postmortem (Le 29/10/2015, à 15:33)
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#3 Le 29/10/2015, à 17:20
- Compte anonymisé
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Bonjour,
je propose cette solution (qui tri par ordre alphabétique en plus) :
for b in $(cat accepted.txt | awk '{print $1}'|uniq|sort)
do echo $b
cat accepted.txt|grep $b|awk '{print $2}'|uniq -c|sort
done
$ sh test.sh
rara
1 192.168.2.18
riri
1 192.168.1.19
roro
1 192.168.1.38
2 192.168.1.22
titi
1 192.168.1.17
2 192.168.1.8
le nombre d'occurence est affiché avant l'adresse IP
Dernière modification par Compte anonymisé (Le 29/10/2015, à 17:23)
#4 Le 29/10/2015, à 18:23
- nqrkko
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Bonsoir à vous,
Merci pour tes remarques Postmortem, elles vont me permettre de m'améliorer (et j'ai du travail) dans le scripting en "bash"
Anonyme68, merci beaucoup pour ce très léger script, il est concis et répond tout à fait à mes attentes !
Bonne soirée à vous !
Hors ligne
#5 Le 29/10/2015, à 19:16
- Postmortem
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Bonjour,
je propose cette solution (qui tri par ordre alphabétique en plus) :
for b in $(cat accepted.txt | awk '{print $1}'|uniq|sort) do echo $b cat accepted.txt|grep $b|awk '{print $2}'|uniq -c|sort done
résultat a écrit :$ sh test.sh
rara
1 192.168.2.18
riri
1 192.168.1.19
roro
1 192.168.1.38
2 192.168.1.22
titi
1 192.168.1.17
2 192.168.1.8le nombre d'occurence est affiché avant l'adresse IP
« cat | grep | awk | .... » c'est quand même laid !!
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#6 Le 29/10/2015, à 20:59
- Compte anonymisé
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Oui j'ai fait en 5 minutes
Il y a surement moyen de faire plus propre
#7 Le 29/10/2015, à 21:18
- Compte anonymisé
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
voilà un peu plus propre :
for b in $(awk '{print $1}' accepted.txt|uniq|sort)
do echo $b
grep $b accepted.txt|awk '{print $2}'|uniq -c|sort
done
#8 Le 30/10/2015, à 05:48
- pingouinux
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Bonjour,
@Anonyme68 #7 : uniq ne voit les lignes identiques que si elles sont consécutives. Je pense que le sort doit être avant.
Ajouté :
La même chose en python, mais c'est moins concis
#!/usr/bin/env python
with open('./accepted.txt','r') as f: ligs=f.readlines()
tab={}
for lig in ligs:
user,ip=lig.split()
if not user in tab: tab[user]={}
if not ip in tab[user]: tab[user][ip]=0
tab[user][ip]+=1
for user in sorted(tab):
print(user)
for ip in tab[user]: print("\t%-15s : %2s fois"%(ip,tab[user][ip]))
Édité : Un peu plus condensé
#!/usr/bin/env python
with open('./accepted.txt','r') as f:
tab={}
for lig in f:
user,ip=lig.split()
tab.setdefault(user,{})
tab[user].setdefault(ip,0)
tab[user][ip]+=1
for user in sorted(tab):
print(user)
for ip in tab[user]: print("\t%-15s : %2s fois"%(ip,tab[user][ip]))
Dernière modification par pingouinux (Le 30/10/2015, à 07:13)
Hors ligne
#9 Le 30/10/2015, à 09:26
- Compte anonymisé
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Bien vu pingouinux !
Du coup :
for b in $(awk '{print $1}' accepted.txt|sort|uniq)
do echo $b
grep $b accepted.txt|awk '{print $2}'|sort|uniq -c
done
#10 Le 30/10/2015, à 12:47
- Postmortem
Re : [RESOLU] Bash : Extraire et compter le nombre d'occurences
Version triée avec gawk :
awk '{ nb[$1][$2]++ }
END { nb_users=asorti(nb, users)
for (i=1; i<=nb_users; i++) {
printf "%s\n", users[i]
nb_ips=asorti(nb[users[i]], ips)
for (j=1; j<=nb_ips; j++) printf "%s : %s fois\n", ips[j], nb[users[i]][ips[j]]
}
}' accepted.txt
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne