Précédent   Forum des professionnels en informatique > Systèmes > Linux > Applications > Shell
Shell Vos questions sur l'utilisation des commandes shell
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 21/02/2011, 16h02   #1
Nouveau Membre du Club
 
Inscription : septembre 2006
Messages : 105
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 105
Points : 32
Points : 32
Par défaut Extraire valeur d'un stream (regexp ?)

Bonjour,
je continue dans mes question de débutants

Lorsque j'appelle une url dans mon script (via curl) elle me renvoit un message xml.
Dans ce xml, j'aimerais récup une infos, plus précisement la valeur entre <id>toto</id> pour que je puisse l'utiliser dans la suite de mon script

J'ai cherché un peu, je suis tombé sur sed mais je trouve ça très complexe au premier abord (et j'ai pas trop de souci avec les regexp en général).

Donc si vous avez la solution ou que vous pouvez me guider...

Merci
Sylver--- est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 21/02/2011, 16h13   #2
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
J'ai une réponse de noob, mais il y a sûrement plus propre

Code :
sed -n 's/.*<id>\(\w*\)<\/id>.*/\1/p'
-n
> pour ne pas afficher les lignes

s/.../.../ (s/.*<id>\(\w*\)<\/id>.*/\1/p)
> chercher le pattern compris entre les 2 premiers slashs et le remplace par le contenu entre les 2 derniers slashs

.*<id>\(\w*\)<\/id>.*
> texte chercher : quelque chose ou pas, suivi de <id>, puis d'un mot (\w est à adapter) (les parenthèses échappées sont uniquement là pour mémoriser cette partie) puis suivi de </id> et d'éventuellement quelque chose

\1
> fait référence au premier groupe de parenthèses du pâté (.*<id>\(\w*\)<\/id>.*)précédent

p
> affiche la ligne correspondante

Donc la commande cherche une ligne correspondant à quelque chose ou pas, suivi de <id>, puis d'un mot puis terminé par </id> et éventuellement autre chose. Elle remplace cette ligne par ce qui est entre <id> et </id> et affiche le résultat...
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 21/02/2011, 16h30   #3
Nouveau Membre du Club
 
Inscription : septembre 2006
Messages : 105
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 105
Points : 32
Points : 32
Réponse très rapide, merci bien
Sylver--- est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 21/02/2011, 17h20   #4
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
de rien ^^ tu peux cliquer sur résolu si c'est ok, à moins que tu ne préfères attendre une réponse plus jolie (ce qui devrait être possible )
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 21/02/2011, 17h55   #5
Expert Confirmé
 
Inscription : janvier 2011
Messages : 970
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 970
Points : 2 871
Points : 2 871
Citation:
Envoyé par Alek-C Voir le message
à moins que tu ne préfères attendre une réponse plus jolie (ce qui devrait être possible )
Salut,

Plus jolie peut être pas mais j'ai plus coutume de faire comme suit :

Code :
sed -n 's/.*<id>\(\[^<]*\)<.*/\1/p'
__________________
$ man woman
Il n'y a pas de page de manuel pour woman.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 22/02/2011, 15h07   #6
Nouveau Membre du Club
 
Inscription : septembre 2006
Messages : 105
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 105
Points : 32
Points : 32
Je continue avec le sed
Là je cherche à obtenir le nom du rep du fichier (donc 56) :
Code :
1
2
 
dirname ftp/56/toto.zip | sed -n 's/*\/\(\w\)$/\1/p'
(n'importe quoi * suivi de slash \/ suivi d'un mot \(w\) suivi de la fin de ligne - pour que si jamais dirname me renvoi alphonse/ftp/56 je n'ai pas ftp/56 dans \1)

Et cela ne me renvoi rien donc pas pratique pour trouver l'erreur

Une idée ?
Sylver--- est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 22/02/2011, 15h14   #7
Expert Confirmé
 
Inscription : janvier 2011
Messages : 970
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 970
Points : 2 871
Points : 2 871
Salut,

Code :
dirname ftp/56/toto.zip | sed 's#.*/##'


Sinon, sans sed :

Code :
$ basename $(dirname ftp/56/toto.zip)
__________________
$ man woman
Il n'y a pas de page de manuel pour woman.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 22/02/2011, 15h38   #8
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
"n'importe quoi" c'est .* et pas * tout seul
* signifie : le caractère précèdent répété 0 ou plusieurs fois
. signifie n'importe quel caractère (sauf fin de ligne selon les options)

\w correspond à un seul caractère, donc si tu veux pouvoir en capturer plusieurs, il te faut une * derrière : \w*

Code :
dirname ftp/56/toto.zip | sed -n 's/.*\/\(\w*\)$/\1/p'
Après, tu n'as pas besoin de dirname et d'une "capture" dans sed: dirname isolant la partie "dossier", il suffit que tu vires le début ! De plus, inutile ici d'utiliser le -n et le p puisque tu n'as qu'une seule ligne (ces deux options servent uniquement à ne pas afficher toutes les lignes, mais ici, tu n'as qu'une ligne, elles sont donc inutiles).

Code :
dirname ftp/56/toto.zip | sed 's/.*\///'
ou plus lisible (les / peuvent être remplacées par d'autres caractères):
Code :
dirname ftp/56/toto.zip | sed 's#.*##'
Sinon, tu peux utiliser les options de bash:

Code :
1
2
3
4
fichier="ftp/56/toto.zip"
dossier=${fichier%/*}
 
echo ${dossier##*/}
${fichier%/*} > supprime la plus petite partie à droite de $fichier qui ressemble à /* (un slash suivi de n'importe quoi, ici, pas de . !!)
${dossier##*/} > supprime la plus grande partie à gauche de $dossier qui ressemble à */ (n'importe quoi se terminant par slash)
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 22/02/2011, 15h40   #9
Nouveau Membre du Club
 
Inscription : septembre 2006
Messages : 105
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 105
Points : 32
Points : 32
Plein de réponses, merci bien
Sylver--- est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 23/02/2011, 09h49   #10
Expert Confirmé
 
Inscription : janvier 2011
Messages : 970
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 970
Points : 2 871
Points : 2 871
Citation:
Envoyé par Alek-C Voir le message
* signifie : le caractère précèdent répété 0 ou plusieurs fois
En fait non, ce n'est pas le caractère précédent répété, mais une séquence de zéro, une ou plusieurs occurrence(s) de l'expression précédente.

Quand tu dis "le caractère précédent répété 0 ou plusieurs fois", cela sous-entends qu'il doit être présent au moins une fois avant (enfin c'est ce que je comprends expliqué comme ça)

Citation:
\w correspond à un seul caractère, donc si tu veux pouvoir en capturer plusieurs, il te faut une * derrière : \w*
Ce serait plutôt "n'importe quel caractère de la classe : [A-Za-z0-9_] (underscore _ compris)"

__________________
$ man woman
Il n'y a pas de page de manuel pour woman.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 24/02/2011, 17h38   #11
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
Merci des précisions

c'est vrai que j'ai cherché à raccourcir un peu trop mes explications et que du coup, ça n'en est pas forcément plus clair

Cela dit, je trouve que "une séquence de zéro, une ou plusieurs occurrence(s) de l'expression précédente" peut également prêter à confusion !

une séquence de zéro => 000000

pas facile de définir le * sans exemple en fait...
Citation:
* indique que ce qui précède est absent ou présent, y compris plusieurs fois
?

Sinon, pour le \w, là, aucun souci : je suis allé au plus court sans rentrer dans les détails, et ta définition est juste (mais ne parle pas forcément à quelqu'un qui ne connaît pas du tout les regexps), donc pour traduire :
Citation:
\w regroupe les lettres a à z (en minuscule) et A à Z (en majuscule) ainsi que les chiffres 0 à 9 et le caractère _ (underscore)
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 24/02/2011, 17h48   #12
Expert Confirmé
 
Inscription : janvier 2011
Messages : 970
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 970
Points : 2 871
Points : 2 871
C'est clair que le plus dur dans les regex tout compte fait, c'est de les expliquer clairement
__________________
$ man woman
Il n'y a pas de page de manuel pour woman.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 04/03/2011, 15h35   #13
Nouveau Membre du Club
 
Inscription : septembre 2006
Messages : 105
Détails du profil
Informations forums :
Inscription : septembre 2006
Messages : 105
Points : 32
Points : 32
(re)Bonjour
Est ce que qqun pourrait m'expliquer : sed 's#.*/##' ?
Je ne comprend pas les #
Et là j'essaye de recupérer le rep précédent et je n'y arrive pas
dans /toto/coco/pouet/test.zip, récupérer la valeur de "coco"

Merci
Sylver--- est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 04/03/2011, 15h57   #14
Expert Confirmé
 
Inscription : janvier 2011
Messages : 970
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : janvier 2011
Messages : 970
Points : 2 871
Points : 2 871
Citation:
Envoyé par Sylver--- Voir le message
(re)Bonjour
Est ce que qqun pourrait m'expliquer : sed 's#.*/##' ?
Je ne comprend pas les #
Par défaut le séparateur pour la commande de substitution (s) est le slash (/). Quand on retrouve ce caractère dans le motif à substituer (ou à rechercher), 2 choix s'offrent à nous.
Soit on échappe le caractère, mais bien souvent ça devient vite illisible et laborieux, soit on change de caractère séparateur en en choisissant un qui ne soit pas contenu dans le motif à substituer, comme le dièse (#) dans ce cas. Mais on aurait pu mettre n'importe quoi :

Code :
1
2
3
4
sed 's|.*/||'
sed 's,.*/,,'
sed 'sA.*/AA'     #(si le motif ne contient que des minuscules)
etc.



Citation:
Et là j'essaye de recupérer le rep précédent et je n'y arrive pas
dans /toto/coco/pouet/test.zip, récupérer la valeur de "coco"

Merci
Là il faut jouer avec les références arrières.

Code :
1
2
3
$ echo "/toto/coco/pouet/test.zip" | sed 'sA/[^/]*/\([^/]*\).*A\1A'
coco
$
__________________
$ man woman
Il n'y a pas de page de manuel pour woman.
zipe31 est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 07/03/2011, 11h03   #15
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
Si tu commences à vouloir récupérer des répertoires parents, tu peux aussi réfléchir à utiliser autre chose que sed selon le besoin (awk, cut, perl, ...) parce qu'il y a un moment où la lecture devient ardue comme le montre l'exemple de zipe31

(edit) avec awk, ça donnerait ceci par exemple :
Code :
1
2
$ echo "/toto/coco/pouet/test.zip" | awk -F/ '{print $(NF-2)}'
coco
NF indiquant le dernier champ, NF-1 te renvoie le dernier dossier et NF-2 l'avant dernier (etc...)

Tu as aussi des fonctions intégrées à bash:
Code :
1
2
3
$ export test="/toto/coco/pouet/test.zip"
$ echo ${test%/*/*}
/toto/coco
Après, tout dépend de ce que tu cherches à en faire !
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 12h59.


 
 
 
 
Partenaires

Hébergement Web