[expressions régulières] question preg_match

Résolu/Fermé
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 - 15 oct. 2008 à 15:18
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 - 22 oct. 2008 à 15:17
Bonjour,

Je suis sur un ptit script qui va utiliser des expressions régulières, et j'aurais souhaité avoir une info que je n'ai pas trouvé.

En fait, je veux faire un preg_match sur plusieurs expressions régulières, du style:
preg_match(regexp1 OU regex2 OU regexp3, "un texte à analyser")

avec regexpX étant les différentes expressions que je veux tester.

Mon soucis est donc le suivant:
Est-il possible d'inclure les "conditions" OU dans mon preg_match, ou bien suis-je obligé de multiplier cette ligne autant de fois que j'ai de regexp (dans mon exemple, ca ferait donc 3 fois)?
Et si oui, quel est le symbole de OU? (je parle pas du OU qu'on met dans une classe de caractère hein, mais bien un OU qu'on placerait dans le preg_match.

En espérant bien m'etre fait comprendre, je vous souhaite une bonne journée.

Merci d'avance.

Muad'Dib

22 réponses

kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
15 oct. 2008 à 15:46
Salut,

En utilisant le pipe:
(exp1)|(exp2)
1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
22 oct. 2008 à 13:34
Effectivement, find ne cherche que les fichiers et en plus ça passe par un système d'expression spécifique.
Dis moi tu connais un peu le python?
1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
22 oct. 2008 à 15:16
Mouhahaaaaa

Je viens d'en finir avec mon script!!

Donc au final, j'ai utilisé la fonction -regex de find. En y allant pas à pas, j'ai réussi à bien voir la syntaxe (ca changeait pas énormément du perl) des regexp.

Voici donc mes scripts:
#!/bin/sh
find . -type d -regex '^\./[a-zA-Z0-9_ ()-]+/CONTRAT/[0-9][a-zA-Z0-9_ ()-]+' -exec /home/thib/BupCOURvoip/creadoc080920/analyse {} \;

Je répère cette ligne pour chaque style de regexp que je souhaite traiter, et ca fonctionne au poil =)

En plus, voici le ptit script qui traite les répertoires voulus:
#!/bin/sh
chmod a-x $1


Pour le script analyse, j'ai juste mis un ptit chmod, histoire de tester; mais on peut remplacer ca par ce qu'on veut.

Voili voilou.

Pour finir, je tenais vraiment à te remercier pour ton aide, kilian.

Donc voilà, un grand merci à toi, et bonne journée à tous les linuxiens =)

Amicalement

Muad'Dib
1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
22 oct. 2008 à 15:17
Ouf, bon bah c'est bien ^_^
1

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
15 oct. 2008 à 15:50
Ok, nikel

Merci bien kilian :)

Jvais aller tester ca de suite
0
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
15 oct. 2008 à 16:52
Hum, jcommence à me casser un peu les dents lol...
J'essaie d'intégrer cela dans un script, et la syntaxe semble foirer quelque part sur le preg_match :s

voici mon script:
function AnalyseEtTraite ()
{
$repname=$1
if [preg_match ("#^\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\(CHANTIER|CLIENT|CONTRAT|PREVENTION|PRIME|SINISTRE)\\$|^\\[a-zA-Z0-9_ ()-]+\\CHANTIER\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\CHANTIER\\[a-zA-Z0-9_ ()-]+\\DOSSIER\\$|^\\[a-zA-Z0-9_ ()-]+\\CONTRAT\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\CONTRAT\\[a-zA-Z0-9_ ()-]+\\DOSSIER\\$|^\\[a-zA-Z0-9_ ()-]+\\PREVENTION\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\PRIME\\CIES\\$|^\\[a-zA-Z0-9_ ()-]+\\SINISTRE\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\SINISTRE\\[a-zA-Z0-9_ ()-]+\\(ASSURANCE|DOSSIER|EXPERTISE)\\$#",$repname)] ; then
   echo $1
fi
};
find . -type d -exec AnalyseEtTraite {} \;


Si je simplifie le gros paté, ca équivault à ca:
function AnalyseEtTraite ()
{
$repname=$1
if [preg_match ("#regexp1|regexp2|regexp3#",$repname)] ; then
   echo $1
fi
};
find . -type d -exec AnalyseEtTraite {} \;


Et quand j'exécute le script, il me donne le message suivant:
 line 4: syntax error near unexpected token `"#^\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\(CHANTIER|CLIENT|CONTRAT|PREVENTION|PRIME|SINISTRE)\\$|^\\[a-zA-Z0-9_ ()-]+\\CHANTIER\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\CHANTIER\\[a-zA-Z0-9_ ()-]+\\DOSSIER\\$|^\\[a-zA-Z0-9_ ()-]+\\CONTRAT\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\CONTRAT\\[a-zA-Z0-9_ ()-]+\\DOSSIER\\$|^\\[a-zA-Z0-9_ ()-]+\\PREVENTION\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\PRIME\\CIES\\$|^\\[a-zA-Z0-9_ ()-]+\\SINISTRE\\[a-zA-Z0-9_ ()-]+\\$|^\\[a-zA-Z0-9_ ()-]+\\SINISTRE\\[a-zA-Z0-9_ ()-]+\\(ASSURANCE|DOSSIER|EXPERTISE)\\$#",$repname'


Pour finir, je tenais juste à préciser que j'écris ce script dans un terminal, sur Debian.

Voilà, donc je reste preneur de toute info utile (ou pas :p ).
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
15 oct. 2008 à 16:59
Tu as oublié de mettre tes expressions entre parenthèses.

abcd|efgh ça signifie abc(d ou e)fgh
Alors que (abcd)|(efgh) ça signifie ce que tu voulais ;-)

Après l'erreur de syntaxe par contre je ne saurais pas trop te dire.... Ya beaucoup de choses....
0
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
15 oct. 2008 à 17:12
Oki, j'ai donc modifié cela... mais c'est sure que les regexp prennent pas mal de place ><

Sinon, après modif, voici le nouveau message d'erreur:
./DroitsCour: line 4: syntax error near unexpected token `newline'
./DroitsCour: line 4: `if [preg_match ('

avec DroitCour étant le nom du script

NB: le message d'erreur s'arrete bien au dernier " ' "... le terminal n'a pas mis tout le paté de regexp

C'est là où je me demande si preg_match est bien "installé" sur ma debian
0
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
15 oct. 2008 à 17:24
Juste au cas où ca paraisse plus clair, j'ai refait la mise en forme du script:

function AnalyseEtTraite ()
{
$repname=$1
if [preg_match (
"#
(^\\[a-zA-Z0-9_ ()-]+\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\(CHANTIER|CLIENT|CONTRAT|PREVENTION|PRIME|SINISTRE)\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\CHANTIER\\[a-zA-Z0-9_ ()-]+\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\CHANTIER\\[a-zA-Z0-9_ ()-]+\\DOSSIER\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\CONTRAT\\[a-zA-Z0-9_ ()-]+\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\CONTRAT\\[a-zA-Z0-9_ ()-]+\\DOSSIER\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\PREVENTION\\[a-zA-Z0-9_ ()-]+\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\PRIME\\CIES\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\SINISTRE\\[a-zA-Z0-9_ ()-]+\\$)|
(^\\[a-zA-Z0-9_ ()-]+\\SINISTRE\\[a-zA-Z0-9_ ()-]+\\(ASSURANCE|DOSSIER|EXPERTISE)\\$)
#",$repname)] ; then
   echo $1
fi
};
find . -type d -exec AnalyseEtTraite {} \;
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
15 oct. 2008 à 17:41
IL faut que ton expression soit une seule ligne....
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
15 oct. 2008 à 17:27
Mais j'y pense, tu peux pas faire:
if [commande (prout, bidule)]

Pour tester une commande il faut que tu fasses:
if [ -n "$( commande prout bidule )"  ]

Le -n teste si la chaîne n'est pas vide.
0
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
16 oct. 2008 à 17:07
sympa le nom lol

Chui allé voir, histoire d'en apprendre un peu plus à ce sujet, et jpense qu'un #!/usr/bin/perl
serait plus approprié... quoi que :p

Enfin bref, je continue de voir ca de mon coté; merci encore pour tout.

++
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
16 oct. 2008 à 17:40
Finalement j'ai pas le temps de tester un script :-s
Je pourrais pas regarder avant la semaine prochaine en plus, désolé :-s
-1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
16 oct. 2008 à 10:39
mouarf, je crois avoir décelé une nouvelle erreur :s

Oui, sinon, j'ai résolu mon soucis précédent; j'avais oublié de définir le type de script en en tete, et j'avais zappé le $ devant la fonction, dans mon find.

Seulement je me suis apercu qu'avec ma commande, ca traite tous les répertoires sans exception... (je veux faire un chmod sur les répertoires ciblés).

J'ai essayé de changer mes antislash en slash, mais ca donne toujorus la meme chose. Par contre, j'ai pas mis un antislash derriere. Voici un exmeple de regexp:
#^/[a-zA-Z0-9_ ()-]+/CHANTIER/[a-zA-Z0-9_ ()-]+/$#


Je précise que mes slash sont là pour marquer les séparations entre chaque répertoire.

En espérant que ca vous parle^^
-1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
16 oct. 2008 à 14:17
Je viens de capter un truc avec les regexp... un truc qui va pas me convenir du tout lol...

Quand je fais une regexp comme celle là:
#^/[a-zA-Z0-9_ ()-]+/CHANTIER/[a-zA-Z0-9_ ()-]+/$#

Ca va me donner TRUE pour le répertoire /toto/CHANTIER/tutu/

Mais ca va aussi me donner TRUE pour /toto/CHANTIER/tutu/etzut ... cest bien ca non?

Helas, je souhaite juste que la regexp me donne TRUE pour /toto/CHANTIER/tutu/ et que ca aille pas "valider" tous les sous répertoires de la meme arborescence :s

Y aurait-il un moyen de le spécifier quelquepart?
-1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
16 oct. 2008 à 14:25
Essaie comme ça:
#^/[a-zA-Z0-9_ ()-]+?/CHANTIER/[a-zA-Z0-9_ ()-]+?/$#
0
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
16 oct. 2008 à 14:57
raaa, ca commence a devenir pesant cette histoire de regexp lol...

Bon, histoire d'etre sure que je soie sur les bons rails:

- j'ai mis ca en debut de script:
#!/bin/sh

Je sais pas trop ce que ca veut dire... mais j'ia cruc omprendre que je devais initialiser un langage, pour que le shell comprenne mon script.
Mais bon, je suis vraiment pas certain qu'un terminal debian comprenne un preg_match ...
Si vous pouviez me confirmer ce point, ca serait bien cool.

Sinon, pour ta dernière remarque, kilian, je suis pas sure que ca marche ton truc avec "+?" (ca voudrait dire répéter au moins une fois, et/ou répéter 0,1 ou plusieurs fois, d'où une redondance... à voir). J'ai testé, ca n'a rien changé (a mon avis, c'est car le preg_match ne doit pas du tout marcher, donc normal que ca change rien).

Enfin bref, j'avoue que je me sens un poil dépassé là...

(en tout cas, vraiment merci ton aide kilian; sans toi, j'aurais surement pas mal de cheveux en moins :p)
-1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
16 oct. 2008 à 16:19
#!/bin/sh

Je sais pas trop ce que ca veut dire... mais j'ia cruc omprendre que je devais initialiser un langage, pour que le shell comprenne mon script.


Oui, c'est un Sha-Bang :-)

Bonche, je suis au boulot et j'ai un Linux dans une machine virtuelle, je vais tester quelques expressions régulières pour résoudre ton soucis.
-1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
17 oct. 2008 à 09:25
EDIT: bon, j'ai rien dit. Je retravaille dans mon ptit coin, et jvous redonne des nouvelles fraiches dès que possible.
A pluche!


Juste une petite question, et jpense deja que ca devrait bien m'aider:
comment faire pour rechercher une chaine exacte, et pas ces dérivés?
Je m'explique par un exemple:
j'ai l'arborescence suivante:
/CHANTIER/NomChantier/DOSSIER
/DIVERS
/DIVERS

Je souhaite donc ne sélectionner que les répertoires CHANTIER, NomChantier et DOSSIER, pour leur attribuer des droits spécifiques.
J'ai tenté avec des expressions régulières, mais jviens de m'apercevior qu'avec mes regexp, ca renvoie toute les sous-couches avec. Donc je vois pas trop comment faire... en gros, jvoudrais qu'un preg_match (#guitare#, "j'aime la guitare") me renvoi un false; sinon, tous les sous-répertoires seront TRUE :s

Si chui pas bien clair, hésitez pas à me le dire, j'essairais de clarifier la chose.

Merci d'avance.

Muad'Dib
-1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
17 oct. 2008 à 14:57
Salut,

Tu fais comme ça:
^machaineconstante$
-1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
17 oct. 2008 à 17:20
ouep, c'est ca^^

J'ai pas mal avancé sur mon script là. Donc maintenant, ca marche "correctement". Il me manque juste à mettre en place la récursivité, pour qu'il aille voir dans les sous-répertoires.

Voici mon code pour le moment:

#!/usr/bin/perl
my $string2 = '^[a-zA-Z0-9_ ()-]+$';
my ($fichier, $dossier) = (undef, '/home/thib/RepAAnalyser');
opendir (my $dir, $dossier) or die "$dossier n'existe pas !";
my @files = readdir $dir;
foreach $fichier (@files)
{
  if ((-d "$dossier/$fichier") && ($fichier =~ m/$string2/))
     {  print "$fichier\n";
        AnalyseDir ("$dossier/$fichier");
     };

}
closedir $dir;


Ce code me renvoi bien les répertoires contenus dans RepAAnalyser, mais pas les sous répertoires.

J'espère que la suite sera pas trop laborieuse :p
-1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
20 oct. 2008 à 15:28
hum,

Personne aurait une ptite idée pour avoir une récursivité de ce programme?
-1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
22 oct. 2008 à 11:22
Rebonjour,

J'ai un peu avancé sur mon script, mais je patauge encore :s

En fait, je viens de m'apercevoir que la fonction grep analyse des chaines de caractères, ou bien des contenus de fichier. Par contre, ca a pas l'air de marcher sur le renvoi d'un find, meme si c'est une chaine de caractère... j'aurais bien aimé avoir confirmation de cela.
J'ai fait un ou deux test de mon coté, et quand j'envoi le resultat de mon find dans un fichier, ca va nikel, mais quand je lance le grep directement à la suite du find, ca ne marche pas.
Vu le nombre de répertoires à analyser (environ 100 000), je me vois pas trop les mettre tous dans un fichier que j'analyserais par la suite.

Auriez vous une ou deux pistes à me donner? en gros, je cherche maintenant une fonction qui marche comme grep, mais qui peut travailler sur des répertoires.

Je vous laisse ici mes scripts:
- script find:
#!/bin/sh
find . -type d -exec /home/thib/BupCOURvoip/creadoc080920/analyse {} \;

- script de la fonction analyse:
#!/bin/sh
grep ^\./infrasud $1
if [ "$?" -eq "0" ]; then
echo $1
fi
-1
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
22 oct. 2008 à 11:28
Normalement find est fait pour ça.
Tu veux retenir quoi comme style de chemin de fichier?
-1
muaddibx Messages postés 76 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 12 juin 2009 1
22 oct. 2008 à 11:35
En fait, je souhaite sélectionner un ensemble de répertoires (grace aux regexp^^), et leur attribuer certains droits (setgid en particulier).

Donc avec le find, jtrouve tous les répertoires. Mais j'arrive pas à n'en prendre qu'une partie pour les traiter par la suite.
Enfin, j'y arrive si je mets tous les répertoires dans un fichier; avec grep, ca marche. Mais je ne souhaite pas mettre cette liste dans un fichier, car j'ai bien trop de répertoires.

EDIT: et donc comme style de chemin de fichier, cest un peu compliqué à expliquer car yen a pas mal de styles. Cest pour cela que je souhaitait utiliser les expressions régulières
-1