#1 Le 09/09/2012, à 11:05
- arnaud_d
Sed et expressions régulières
Bonjour,
Sed et awk restent ma bête noire. A chaque fois que j'ai besoin de les utiliser je passe deux jours à me prendre la tête, lire tous les tutos que je peux pour au final venir demander de l'aide ici sans jamais progresser.
Cette fois-ci je m'arrache les cheveux, tellement tout ce que je lis sur internet semble me donner raison, mais non, ça ne veut pas fonctionner.
Ma mission: Récupérer une sous-chaine en connaissant le contexte dans la même ligne (mots clés)
En réalité je cherche à isoler une adresse dans un fichier HTML mais pour la localiser je souhaiterais rechercher son contexte (par exemple l'intitulé du lien). Déjà si j'arrivais à faire ce qui suit, ce serait un bon début !
Imaginons que j'aie la phrase "arnaud aime ubuntu" comme puis-je extraire "aime" ?
Solution 1 : j'utilise la substitution
arnaud@arnaud-laptop:~$ echo "arnaud aime ubuntu" | sed -n 's/\<arnaud \>\([a-z]*\)\< ubuntu\>/\1/'
Non ça ne marche pas.
Solution 2 : j'utilise print
arnaud@arnaud-laptop:~$ echo "arnaud aime ubuntu" | sed -n '/\<arnaud \>\([a-z]*\)\< ubuntu\>/ p'
Toujours pas !
Merci à ceux qui voudront bien m'éclairer !
EDIT : j'avais oublié le -n de sed
Dernière modification par arnaud_d (Le 09/09/2012, à 11:11)
Hors ligne
#2 Le 09/09/2012, à 11:51
- arnaud_d
Re : Sed et expressions régulières
Bonjour gigiair et merci pour ta réponse si rapide.
Mon problème est générique, je veux par exemple extraire une chaîne de caractère en connaissant ce qu'il y a avant et après.
Exemple :
1. J'ai "0982BonjourUUU" je veux pouvoir récupérer "Bonjour" en connaissant "0982" et "UUU"
2. J'ai "<a href="file.pdf">Mon fichier</a>", je veux pouvoir récupérer "file.pdf" en connaissant "<a href=""et "">Mon fichier</a>""
3. J'ai "adresse : arnaud@ubuntu.com", je veux pouvoir récupérer arnaud" en connaissant "adresse : " et "@ubuntu.com"
merci !
Dernière modification par arnaud_d (Le 09/09/2012, à 11:52)
Hors ligne
#3 Le 09/09/2012, à 11:53
- miniSeb
Re : Sed et expressions régulières
En réalité je cherche à isoler une adresse dans un fichier HTML mais pour la localiser je souhaiterais rechercher son contexte (par exemple l'intitulé du lien).
Sans donner la réponse en entier, l'expression régulière à constituer sera de ce genre-ci :
<a href="([^"]+)">INTITULÉ DU LIEN</a>
que l'on peut décortiquer comme suit :
<a href=" # c'est un lien
([^"]+)"> # sauvegarde tout ce qu'il y a entre href=" et "> // selon les logiciels, la variable sera nommée \1 ou $1
INTITULÉ DU LIEN # l'identifiant qui permet de récupérer la bonne url
</a> # fin du lien (optionnel)
En fait, ce qui t'intéresse ici dans les expressions régulières est la notion de capture
Dernière modification par miniSeb (Le 09/09/2012, à 11:54)
Hors ligne
#4 Le 09/09/2012, à 12:01
- arnaud_d
Re : Sed et expressions régulières
En fait, ce qui t'intéresse ici dans les expressions régulières est la notion de capture
Oui c'est tout à fait ça.
J'ai essayé d'adapter ce que tu m'as indiqué à mon exemple mais ça ne marche pas :
arnaud@arnaud-laptop:~$ echo "arnaud aime ubuntu" | sed -n 's/arnaud([a-z]+)ubuntu/\1/'
sed: -e expression #1, char 26: invalid reference \1 on `s' command's RHS
Saurais-tu pourquoi ?
Dernière modification par arnaud_d (Le 09/09/2012, à 12:10)
Hors ligne
#5 Le 09/09/2012, à 12:25
- miniSeb
Re : Sed et expressions régulières
De un, l'option -n doit être remplacée par -r.
De deux, tu as oublié les espaces dans ta regex : il n'y a donc pas de match ; donc sed échoue.
echo "arnaud aime ubuntu" | sed -r 's/arnaud ([a-z]+) ubuntu/\1/'
Hors ligne
#6 Le 09/09/2012, à 12:30
- credenhill
Re : Sed et expressions régulières
hello
avec awk
echo "arnaud aime ubuntu" | awk '{print $2}'
Hors ligne
#7 Le 09/09/2012, à 12:31
- miniSeb
Re : Sed et expressions régulières
Là, ça requiert de connaître la position de l'élément à matcher ; c'est différent de connaître le contexte
Hors ligne
#8 Le 09/09/2012, à 13:14
- arnaud_d
Re : Sed et expressions régulières
Merci miniSeb,
Du coup j'ai un autre exemple qui marche :
$ echo "0982BonjourUUU" | sed -r 's/0982([A-Za-z]+)UUU/\1/'
Bonjour
Mais comment faire pour éviter qu'il me renvoie la chaîne entière s'il n'y a pas eu correspondance ?
$ echo "0982BonjourUUU" | sed -r 's/1234([A-Za-z]+)UUU/\1/'
0982BonjourUUU
Parce qu'en réalité ce que je veux c'est extraire : j'utilise la fonction remplacer (s) de façon détournée.
Dernière modification par arnaud_d (Le 09/09/2012, à 13:18)
Hors ligne
#9 Le 09/09/2012, à 13:26
- miniSeb
Re : Sed et expressions régulières
Combiné -r et -n (sed -rn)
Hors ligne
#10 Le 09/09/2012, à 13:42
- arnaud_d
Re : Sed et expressions régulières
Bon avec tout ça je devrais me débrouiller, je reviens poster si j'ai un soucis.
Merci à tous.
Hors ligne
#11 Le 11/09/2012, à 10:34
- arnaud_d
Re : Sed et expressions régulières
Re-bonjour,
Pourriez-vous me dire pourquoi aucun des deux exemple suivant ne me permet pas d'extraire "aime" s'il vous plait ?
$ echo "olshfgolhsarnaudaimeubuntulfdjhsjfg" | sed -nr 's/[.+]arnaud(.+)ubuntu[.+]/\1/'
$ echo "olshfgolhsarnaudaimeubuntulfdjhsjfg" | sed -nr 's/.+arnaud(.+)ubuntu.+/\1/'
Merci !
Dernière modification par arnaud_d (Le 11/09/2012, à 10:34)
Hors ligne
#12 Le 11/09/2012, à 15:30
- aduxas
Re : Sed et expressions régulières
Je pense qu'il faut omettre l'option -n, mais plus important, [.+] demande l'occurence d'un point ou d'un signe plus. Ni l'un ni' lautre n'est présent dans la chaine. veux-tu dire .+ tout court, c.a.d au moins un caractere ?
EDit: en gros:
sed -r 's/.+arnaud(.+)ubuntu.+/\1/'
Si tu utilises sed -n, il faut imprimer explicitement avec la commande "p"
Dernière modification par aduxas (Le 11/09/2012, à 15:35)
Hors ligne
#13 Le 11/09/2012, à 16:31
- arnaud_d
Re : Sed et expressions régulières
Excellent ! Merci
Comme je le disais plus haut, je préfère ne rien avoir en retour s'il n'y a pas match.
Donc ceci est parfait pour moi :
echo "olshfgolhsarnaudaimeubuntulfdjhsjfg" | sed -rn 's/.+arnaud(.+)ubuntu.+/\1/p'
Je comprend peu à peu...
Hors ligne
#14 Le 13/09/2012, à 22:10
- arnaud_d
Re : Sed et expressions régulières
Je reviens simplement vous remercier pour votre aide car la "maitrise" (restons modeste tout de même) de sed m'ouvre des portes incroyables. J'ai vraiment l'impression d'avoir passé un step. Je suis devenu un g33k, un vrai.
Pour preuve, je voudrais m'acheter la bio de Steve Jobes sur mon Kindle mais j'attends de voir si le prix ne baisse pas un peu. Admirer ce que l'usage de sed m'a permis de faire : mon ordinateur va tout seul sur amazon.com et me dit si le prix à baissé. C'est génial !
#!/bin/sh
old_price=$((`cat price.txt | tail -n 1`))
new_price=$((`wget "http://www.amazon.fr/Steve-Jobs-ebook/dp/B004W2UBYW" -O - -o /dev/null \
| grep "EUR " -m 2 \
| tail -n1 \
| sed -e 's/^[ \t]*//' \
| sed -nr 's/EUR (.*)/\1/p' \
| sed -nr 's/(.*),(.*)/\1\2/p'`))
real_price=`echo "$new_price" | sed -nr 's/(.*)(.{2})/\1.\2/p'`
if [ $new_price -ge $old_price ] ;
then
notify-send "Steve Jobes" "UP OR EQUAL : $real_price €";
echo "Steve Jobes : no change" | espeak -v en
else
notify-send "Steeve Jobes" "DOWN : $real_price €";
echo "HEY ! The price of the book about Steve Jobes has decreased, it costs now $real_price euros" | espeak -v en -s 200
fi
Dernière modification par arnaud_d (Le 13/09/2012, à 22:12)
Hors ligne
#15 Le 13/09/2012, à 23:59
- aduxas
Re : Sed et expressions régulières
Essaye de comprendre les exemples de manip de tampons sur http://www.gnu.org/software/sed/manual/sed.html. Si tu arrives à tout suivre, j'ai quelques questions pour toi
Sinon,
cat fichier | tail -n 1
fait un peu maladroit. pas besoin de cat; tail prend un nom de fichier aussi (ou plusieurs). Puis, il n'y a pas besoin d'invoquer sed 2x; une seule est plus efficace:
sed -nr -e 'commande1' -e 'commande2'
ou encore
sed -nr 'commande1;commande2'
Beau petit script. Fais-le passer commande en-dessous d'un certain seuil
Hors ligne
#16 Le 14/09/2012, à 07:51
- arnaud_d
Re : Sed et expressions régulières
Merci aduxas, je savais que ce n'était pas parfait et qu'il devait bien y avoir un moyen de cumuler les sed.
Après, l'idée de récurer le prix dans un fichier n'est pas terminée, il manque l'écriture du nouveau prix (un petit echo "$new_price" >> price.txt devrait faire l'affaire).
Je vais aussi essayer de lui faire commander, je vais m’entraîner sur des ebooks gratuit sinon ça va me coûter cher
Hors ligne