Perl-Bash recherche et extraction d'une ligne
Résolu/Fermé
A voir également:
- Perl-Bash recherche et extraction d'une ligne
- Recherche automatique des chaînes ne fonctionne pas - Guide
- Partager photos en ligne - Guide
- Aller à la ligne excel - Guide
- Extraction video youtube - Guide
- Site de vente en ligne particulier - Guide
15 réponses
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 569
22 nov. 2007 à 15:45
22 nov. 2007 à 15:45
Salut,
root@debian:~/trash# cat ccm.pl #!/usr/bin/perl use strict;use warnings; while (<DATA>){ print if /\s[5-9]\d+%/; } __END__ /app 80% /bin 30% /toto 25% root@debian:~/trash# perl ccm.pl /app 80%
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
22 nov. 2007 à 15:53
22 nov. 2007 à 15:53
Salut,
#! /bin/bash while read ligne do if [ "$(grep -o '[0-9][0-9]*' <<<$ligne)" -ge 50 ] then echo "$ligne" fi done < "$1";-))
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 569
22 nov. 2007 à 16:45
22 nov. 2007 à 16:45
Salut,
voilà
voilà
root@debian:~/trash# cat ccm.pl #!/usr/bin/perl use strict;use warnings; while (<>){ print if /\s(?:[5-9]\d|\d{3,})%/; } __END__ root@debian:~/trash# cat phoenix /app 80% /bin 30% /toto 25% root@debian:~/trash# perl ccm.pl phoenix /app 80% root@debian:~/trash# df -h | perl ccm.pl /dev/hda1 8,8G 5,4G 3,0G 65% / /home/jacques/a.iso 571M 571M 0 100% /media/cdrom0je vais t'expliquer plus tard, j'ai améliorer la regex ;-)
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
22 nov. 2007 à 17:20
22 nov. 2007 à 17:20
Voilà le script modifié :
#! /bin/bash # Décommenter pour débuguer #set -xv while read ligne do # On récupère dans une variable le résultat de la commande "grep -o" #+ "grep -o" ne récupère que le motif correspondant à l'expression régulière mise entre guillemets #++ dans ton cas, au moins un chiffre (ou plusieurs) suivi(s) du caractère "%" #+++ le "<<<$variable" est une façon plus simple de lire une variable sur le flux d'entrée num=$(grep -o '[0-9][0-9]*%' <<<$ligne) # On compare la valeur de la variable en l'amputant du caractère "%" à l'aide de l'expansion des #+ variables, voir le man bash à ce sujet #++ et on redirige les erreurs dues à une variable vide vers le néant if [ "${num/\%/}" -ge 50 ] 2>/dev/null then echo "$ligne" fi done < "$1";-))
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 569
22 nov. 2007 à 19:36
22 nov. 2007 à 19:36
#!/usr/bin/perl use strict;use warnings; while (<>){ # cette opérateur permet de lire les lignes # des fichiers passer en arguments print if /\s(?:[5-9]\d|\d{3,})%/; # affiche seulement les lignes # qui correspondent à la regex } __END__/\s(?:[5-9]\d|\d{3,})%/
\s - reconnaît un espace
(?: ) permet le regroupement sans capture
1er alternative [5-9]\d
[5-9]\d - trouves toutes les nombre plus grands que 50 jusqu'à 99
[5-9] - c'est une classe de caractères qui permet de reconnaître 5,6,7,8 ou 9
\d - c'est une classe de caractères qui reconnaît les chiffres de 0 à 9
donc on peut la lire comme ça
50
51
.
.
59
60
.
.69
.
.
90
.
.
99
2ème alternative \d{3,}
reconnaît les nombres de minimum 3 chiffres
elle peut être améliorer vu qu'on cherche les nombres plus grand que 100
ce qui donne [1-9]\d{2,} - nous n'avons pas besoin de reconnaître un group de minimum 3 chiffres qui commence avec 0
l'alternative
| - permet de reconnaître soit la partie gauche soit la partie droite de l'alternative
Voici l'exemple avec la regex modifiée
lami20j@debian:~/trash$ cat ccm.pl #!/usr/bin/perl use strict;use warnings; while (<>){ print if /\s(?:[5-9]\d|[1-9]\d{2,})%/; } __END__ lami20j@debian:~/trash$ df -h | perl ccm.pl /dev/hda7 9,2G 4,6G 4,2G 52% / /dev/hda8 28G 15G 12G 56% /home
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 569
23 nov. 2007 à 10:27
23 nov. 2007 à 10:27
Salut,
if($contenu =~ /(n.*t)/)
{
open(monFile,">../logs/instances/pb_instances.txt");
print monFile"Attention, une instances ne tourne pas :\n $contenu \n";
close(monFile);
Il ne faut pas mettre open à l'intérieur de la boucle while sinon pour chaque ligne contenant not tu auras un appel système assez couteux
Il faut aussi eviter de sauvegarder dans une variable le contenu d'un fichier
tu ouvre le fichier avant la boucle et tu le ferme après
l'écriture tu le fait dans la boucle
Voici une possibilité
Par convention c'est bien d'utiliser les majuscules pour handle de fichier
if($contenu =~ /(n.*t)/)
{
open(monFile,">../logs/instances/pb_instances.txt");
print monFile"Attention, une instances ne tourne pas :\n $contenu \n";
close(monFile);
Il ne faut pas mettre open à l'intérieur de la boucle while sinon pour chaque ligne contenant not tu auras un appel système assez couteux
Il faut aussi eviter de sauvegarder dans une variable le contenu d'un fichier
tu ouvre le fichier avant la boucle et tu le ferme après
l'écriture tu le fait dans la boucle
Voici une possibilité
open LOG,"../logs/cluster/status_cluster.log" or die "E/$ : $!\n"; open MONFILE,">../logs/instances/pb_instances.txt" or die "E/S : $!\n"; while (<LOG>){ print MONFILE "Attention, une instances ne tourne pas :\n $contenu \n" if /\bnot\b/; } close(monFile);
Par convention c'est bien d'utiliser les majuscules pour handle de fichier
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
23 nov. 2007 à 10:31
23 nov. 2007 à 10:31
Salut,
Par convention c'est bien d'utiliser les majuscules pour handle de fichier
Quand on manipule trop de langues, on finit par se mélanger les pinceaux ;-DDD
Par convention c'est bien d'utiliser les majuscules pour handle de fichier
Quand on manipule trop de langues, on finit par se mélanger les pinceaux ;-DDD
Bonjour,
merci à tous les 2 pour votre réponse si rapide !! c'est super j'ai du bash et du per! les 2 codes fonctionnent nikel !
juste une petite chose :
lami20j => comment faire pour aller lire les infos dans un fichier appart ? là il faut que les infos soient sous le _END_
A vous 2 => pour mon exemple j'ai mis "/app 80%" comme exemple ... mais mon fichier est un résultat d'une commande du genre "df -h" ou "bdf -t nfs" ... là si j'utilise vos codes avec mon fichier de résultat j'ai un message d'erreur ... "expression de type entien attendu" ...
merci de m'éclairer pour ne chercher que la valeur xx % dans la ligne ...
derniere petite chose je ne comprend pas exactement:
"print if /\s[5-9]\d+%/;" & "[ "$(grep -o '[0-9][0-9]*' <<<$ligne)" -ge 50 ]"
et c'est mieux de comprendre merci !! :)
merci à tous les 2 pour votre réponse si rapide !! c'est super j'ai du bash et du per! les 2 codes fonctionnent nikel !
juste une petite chose :
lami20j => comment faire pour aller lire les infos dans un fichier appart ? là il faut que les infos soient sous le _END_
A vous 2 => pour mon exemple j'ai mis "/app 80%" comme exemple ... mais mon fichier est un résultat d'une commande du genre "df -h" ou "bdf -t nfs" ... là si j'utilise vos codes avec mon fichier de résultat j'ai un message d'erreur ... "expression de type entien attendu" ...
merci de m'éclairer pour ne chercher que la valeur xx % dans la ligne ...
derniere petite chose je ne comprend pas exactement:
"print if /\s[5-9]\d+%/;" & "[ "$(grep -o '[0-9][0-9]*' <<<$ligne)" -ge 50 ]"
et c'est mieux de comprendre merci !! :)
Whaoo !
tout simplement génial la dernière commande ! je l'ai couplé avec un ssh et du coup j'execute le "df -h" sur un poste distant en filtrant avec le fichier perl !! nikel !
par contre je comprend vraiment pas cette ligne : "print if /\s(?:[5-9]\d|\d{3,})%/;" .... c'est là dedans que tu as choisis de filtrer tout ce qui est au dessus de 50% ??
je ne vois pas trop où ( utilie pour faire une modif' ultérieure :)
merci encore !
tout simplement génial la dernière commande ! je l'ai couplé avec un ssh et du coup j'execute le "df -h" sur un poste distant en filtrant avec le fichier perl !! nikel !
par contre je comprend vraiment pas cette ligne : "print if /\s(?:[5-9]\d|\d{3,})%/;" .... c'est là dedans que tu as choisis de filtrer tout ce qui est au dessus de 50% ??
je ne vois pas trop où ( utilie pour faire une modif' ultérieure :)
merci encore !
Un grand merci à lami20j & jipicy !! :)
merci pour les explications détaillées ! je suis d'autant plus content d'avoir 2 réponses ( bash et Perl ) !
J'ai mis vos messages en "Répondent à la question"
vu que cela rentre dans la meme classe, pourriez vous me dire comment faire quelque chose de similaire avec un mot ?
xxx1 is running
xxx2 is running
xxx3 is not running
xxx4 is running
xxx5 is running
J'arrive à faire une recherche de "not" ... mais je n'arrive pas à afficher juste cette ligne ...
mon code :
# Permet d'utiliser des commandes shell .. ici cat .
use Shell qw(cat);
# On entre le contenu du fichier de log dans la variable $contenu
$contenu= cat("../logs/cluster/status_cluster.log");
# Vérification dans $contenu de la présence du mot "not"
if($contenu =~ /(n.*t)/)
{
open(monFile,">../logs/instances/pb_instances.txt");
print monFile"Attention, une instances ne tourne pas :\n $contenu \n";
close(monFile);
.......
merci :)
merci pour les explications détaillées ! je suis d'autant plus content d'avoir 2 réponses ( bash et Perl ) !
J'ai mis vos messages en "Répondent à la question"
vu que cela rentre dans la meme classe, pourriez vous me dire comment faire quelque chose de similaire avec un mot ?
xxx1 is running
xxx2 is running
xxx3 is not running
xxx4 is running
xxx5 is running
J'arrive à faire une recherche de "not" ... mais je n'arrive pas à afficher juste cette ligne ...
mon code :
# Permet d'utiliser des commandes shell .. ici cat .
use Shell qw(cat);
# On entre le contenu du fichier de log dans la variable $contenu
$contenu= cat("../logs/cluster/status_cluster.log");
# Vérification dans $contenu de la présence du mot "not"
if($contenu =~ /(n.*t)/)
{
open(monFile,">../logs/instances/pb_instances.txt");
print monFile"Attention, une instances ne tourne pas :\n $contenu \n";
close(monFile);
.......
merci :)
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
23 nov. 2007 à 10:04
23 nov. 2007 à 10:04
Re-
Pour n'afficher que la ligne contenant "not" tu peux faire avec sed :
Pour n'afficher que la ligne contenant "not" tu peux faire avec sed :
sed -n '/not/p' fichier;-))
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 569
23 nov. 2007 à 10:33
23 nov. 2007 à 10:33
Hello,
Quand on manipule trop de langues, on finit par se mélanger les pinceaux
Heureusement qu'on ne manipule pas les pinceaux pour mélanger les langues ;-DDDDDD
Quand on manipule trop de langues, on finit par se mélanger les pinceaux
Heureusement qu'on ne manipule pas les pinceaux pour mélanger les langues ;-DDDDDD
jipicy
Messages postés
40842
Date d'inscription
jeudi 28 août 2003
Statut
Modérateur
Dernière intervention
10 août 2020
4 897
23 nov. 2007 à 10:40
23 nov. 2007 à 10:40
;-DD
Bonjour,
ok lami20j je ne savais pas pour les pinceaux-langues ... je vais corriger tout ca .. merci pour "sed" et "if /\bnot\b/"
par contre je reviens juste sur ton code "/\s(?:[5-9]\d|\d{3,})%/ ". si je comprend bien, c'est l'alternative \d qui gère les unités de 50 ... autrement dit :
/\s(?:[5-9]\d|\d{3,})%/ pour 50%
/\s(?:[8-9]\d|\d{3,})%/ pour 80%
/\s(?:[1-9]\d|\d{3,})%/ pour 10%
par contre ... comment faire pour filter ce qui dépasse 85% ?
j'ai honte ... mais j'ai testé :
/\s(?:[8-9][5-9] |\d{3,})%/
cela ne fontionne pas trop ...
merci ;)
ok lami20j je ne savais pas pour les pinceaux-langues ... je vais corriger tout ca .. merci pour "sed" et "if /\bnot\b/"
par contre je reviens juste sur ton code "/\s(?:[5-9]\d|\d{3,})%/ ". si je comprend bien, c'est l'alternative \d qui gère les unités de 50 ... autrement dit :
/\s(?:[5-9]\d|\d{3,})%/ pour 50%
/\s(?:[8-9]\d|\d{3,})%/ pour 80%
/\s(?:[1-9]\d|\d{3,})%/ pour 10%
par contre ... comment faire pour filter ce qui dépasse 85% ?
j'ai honte ... mais j'ai testé :
/\s(?:[8-9][5-9] |\d{3,})%/
cela ne fontionne pas trop ...
merci ;)
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 569
23 nov. 2007 à 12:28
23 nov. 2007 à 12:28
lami20j@debserv:~/trash$ cat aa ligne1 80% ligne2 85% ligne1 87%% ligne1 100% ligne1 10% lami20j@debserv:~/trash$ perl -ne 'print if /(?:8[5-9]|9[0-9]|[1-9]\d{2,})/' aa ligne2 85% ligne1 87%% ligne1 100%Cette fois il y a besoin de 3 alternatives
une pour 85 ... 89
une pour 90 ... 99
une pour 100.............
Dans ton exemple [8-9][5-9] ne peux reconnaître que
85 à 89
95 à 99
mais il te manque de 90 à 94
lami20j
Messages postés
21331
Date d'inscription
jeudi 4 novembre 2004
Statut
Modérateur, Contributeur sécurité
Dernière intervention
30 octobre 2019
3 569
23 nov. 2007 à 19:34
23 nov. 2007 à 19:34
Salut,
voici encore une possibilité plus simple à gérer.
cette fois il s'agit d'une comparaison numérique, tu n'auras qu'à remplacer 85 avec la valeur que tu voudras
voici encore une possibilité plus simple à gérer.
cette fois il s'agit d'une comparaison numérique, tu n'auras qu'à remplacer 85 avec la valeur que tu voudras
lami20j@debserv:~/trash$ cat ccm.pl #!/usr/bin/perl use strict;use warnings; while(<>){ (my $val) = $_ =~ /\D(\d+)%/; next unless $val; print if $val >= 85; } lami20j@debserv:~/trash$ cat aa ligne1 80% ligne2 85% ligne1 87%% ligne1 100% ligne1 10% lami20j@debserv:~/trash$ perl ccm.pl aa ligne2 85% ligne1 87%% ligne1 100%