IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Concatenation de chaine de caractère dans une boucle read $line


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2015
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Novembre 2015
    Messages : 49
    Par défaut Concatenation de chaine de caractère dans une boucle read $line
    Bonjour, je crée un .sh qui récupère une description dans une page web.

    https://www.gokishop.eu/html/fr/arti...57496-all.html

    Je dois récupérer la description:
    Si goki a réussi à les assembler, vos clients sont bien
    entendu capables de les défaire. Mais vont-ils y arriver ?
    Des petits jeux de patience pour les grands amateurs de
    puzzles ! Le set de 18 jeux propose 6 modèles différents
    pour toute la famille.


    Le petit soucis, c'est que pour le faire avec un read line, tout est sur des lignes différentes. Je voudrais donc les concaténer.
    Voici le script fonctionnel que vous pouvez copier coller, il se contente d'afficher les lignes 1 par 1. Je n'arrive pas à faire fonctionner la concaténation, pouvez vous m'aider, merci.



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
    #arg pour fournir plusieurs URL au script
    for arg
    do
     
    while read line
    do 
     
    	#récupérer la description du produit
    	if echo "$line" | grep '<div class="detailtopic">Description</div>'>/dev/null 2>&1
    	then
    		found=0
    		description=""
    		while read nextLine;
    		do
    			#ce if permet de vérifier si on est à la fin de la description qui se termine par </td>
    			if echo "$nextLine" | grep -q "</td>"
    			then
    			    found=1
    			else
    			    found=0
    			fi
     
     
    			if [ $found -eq 1 ]
    			then
    				break
    			fi
     
    			#Lecture de la description ligne par ligne
    			descr=$nextLine
    			echo $descr
     
    			#tentative désespérer de concaténation
    			description=$description$descr
     
    		done
    		#lecture finale de la variable concaténé qui ne fonctionne pas.
    		echo $description
     
    	fi
     
     
    done < <(curl -s $arg)
     
    done

    Vous pouvez lancer le script ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    iMac-de-Quentin:Desktop passio$ ./script.sh https://www.gokishop.eu/html/fr/articles-saisonniers/rentr-e-des-classes/casse-t-tes-et-puzzles/item-2-57496-57496-all.html
    Si goki a réussi à les assembler, vos clients sont bien
    entendu capables de les défaire. Mais vont-ils y arriver ?
    Des petits jeux de patience pour les grands amateurs de
    puzzles ! Le set de 18 jeux propose 6 modèles différents
    pour toute la famille.
     
    pour toute la famille. jeux propose 6 modèles différents ?

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 664
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 664
    Par défaut
    Bonjour,

    c'est à faire en shell POSIX, ou tu peux utiliser un shell un peu avancé comme bash ?

    de toute façon, il faut écrire un algorithme AVANT de coder
    Code pseudo-code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    tantQue lire ligne
        si ligne matchRegex debutSection
        alors
            flag=on
        finSi
        si ligne matchRegex keepLine
        alors
            si existe concat
            alors
                concat=concat + ligne
            autre
                concat=ligne
            finSI
        finSI
        si ligne matchRegex finSection
        alors
            écrire concat
        finSI
    finTantQue
    /!\ pas testé !
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Bonjour

    Ah ! Le retour de onlyonlylight. Alors ? Ça va bien ? Tu es revenu au read line, finalement ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ wget -q -O - "https://www.gokishop.eu/html/fr/articles-saisonniers/rentr-e-des-classes/casse-t-tes-et-puzzles/item-2-57496-57496-all.html" | sed 's/\r//g' | sed -n '/Description/,/<\/td>/H;${g;s/\n/ /g;s/  */ /g;s@</td>@@g;s@^.*Description</div> @@;p;}'
    Si goki a réussi à les assembler, vos clients sont bien entendu capables de les défaire. Mais vont-ils y arriver ? Des petits jeux de patience pour les grands amateurs de puzzles ! Le set de 18 jeux propose 6 modèles différents pour toute la famille.
    Explications :
    • Le premier étage de la conduite télécharge ta page html dans le silence et l'envoie dans la conduite.
    • Ta page html est truffée de caractères "\r" insupportables. Le deuxième étage de la conduite les supprime TOUS, sans nuance.
    • Le troisième étage extrait la description. Pour cela :
      • On écrit rien ("-n")
      • On prend "Description" et le "/td" suivant comme point de repère.
      • Entre ces deux lignes, on stocke.
      • A la fin du document ("$"), on remet l'espace mémoire dans l'espace de travail, et on agit.
      • On supprime les retours à la ligne et les espaces multiples.
      • On supprime les balises qui nous ont servi de repère. (fin)
      • (et début)
      • Puis on affiche (ouf. Enfin)


  4. #4
    Membre averti
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2015
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Novembre 2015
    Messages : 49
    Par défaut
    Salut Flodelarab, oui je suis de retour. Toujours avec des scripts. Je vais bien et j'espère que toi aussi, je te remercie d'être toujours là pour me filer un coup de main.

    Je suis revenu à Read Line... Il faut dire que la dernière fois que j'ai passé 3 jours sur un script pour récupérer 10 valeurs, j'en ai eu de nouveaux besoins quelques moins plus tard comme modèle et j'ai du tout recommencer car j'avais oublié de le sauvegardé après avoir changé de mac... J'ai pu retrouvé une partie sur ce Forum quand même...

    Malheureusement, ta ligne de commande ne renvoie aucun résultat sur mon mac.


    Il faut dire que j'utilise read line car je récupère pas mal de valeurs... je n'ai mis que la partie du script qui ne fonctionne pas... Sinon voici le reste des données que je récupère :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    	if echo "$line" | grep '<div class="itemName">'>/dev/null 2>&1
    	then
    		name=`echo $line | sed s/"<[^>]*>"/""/g`;
    		echo $name;
    	fi
     
     
    	if echo "$line" | grep '<td valign="top" class="label">Article'>/dev/null 2>&1
    	then
    		read nextLine;
    		ref=`echo $nextLine | sed s/"<[^>]*>"/""/g | sed s/"&nbsp;"/""/g`;
    		echo $ref;
    	fi
     
    	if echo "$line" | grep '<td valign="top" class="label">Dimensions'>/dev/null 2>&1
    	then
    		read nextLine;
    		dimensions=`echo $nextLine | sed s/"<[^>]*>"/""/g | sed s/"&nbsp;"/""/g`;
    		echo $dimensions;
    	fi
     
    	if echo "$line" | grep '<td valign="top" class="label">&empty'>/dev/null 2>&1
    	then
    		read nextLine;
    		diametre=`echo $nextLine | sed s/"<[^>]*>"/""/g | sed s/"&nbsp;"/""/g`;
    		echo $diametre;
    	fi
     
     
     
    	if echo "$line" | grep '<td valign="top" class="label">Poids'>/dev/null 2>&1
    	then
    		read nextLine;
    		poidsUnite=`echo $nextLine | sed s/"<[^>]*>"/""/g | sed s/"&nbsp;"/""/g`;
    		echo $poidsUnite;
    	fi
     
    	if echo "$line" | grep '<td valign="top" class="label">Âge'>/dev/null 2>&1
    	then
    		read nextLine;
    		age=`echo $nextLine | sed s/"<[^>]*>"/""/g | sed s/"&nbsp;"/""/g`;
    		echo $age;
    	fi
     
     
     
    	if echo "$line" | grep '<td valign="top" class="label">EAN'>/dev/null 2>&1
    	then
    		read nextLine;
    		EAN=`echo $nextLine | sed s/"<[^>]*>"/""/g | sed s/"&nbsp;"/""/g`;
    		echo $EAN;
    	fi

    Merci N_Bah également pour ton aide, mais ici le soucis n'est pas tellement un problème d'algo mais plutôt de syntaxe ou de manque de compréhension de la manière dont le langage opère pour ma boucle de concaténation.

    J'ai juste besoin de créer un CSV avec les infos du site pour ma conjointe pour lui éviter d'entrer les données de 100 produits à la main....

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 664
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 664
    Par défaut
    le soucis n'est pas tellement un problème d'algo
    si, si.

    par exemple, tu as deux fois test $found -eq 1.
    une deuxième boucle imbriquée est inutile, comme je l'ai montré
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  6. #6
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Windows : CR LF Carriage Return Line Feed, "\r\n", 0d0a en hexa.
    Apple : CR Carriage Return, "\r", 0d en hexa.
    Linux : LF Line Feed, "\n", 0a en hexa.

    Le caractère "\r" revient en début de ligne. Tu ne peux pas travailler avec des trucs pareils dans ta page html. J'illustre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ echo -e "ligne 1"
    ligne 1
    $ echo -e "ligne 1\nligne 2"
    ligne 1
    ligne 2
    $ echo -e "ligne 1\r\nligne 2"
    ligne 1
    ligne 2
    $ echo -e "ligne 1\rligne 2"
    ligne 2
    La ligne 1 a-t-elle disparu dans le dernier cas ? Pas vraiment. Elle a été écrasée !!! À cause de "\r".
    Voilà pourquoi, tous tes tests et observations sont soumis à caution.
    Il faut nettoyer le fichier en entrée.

    Ensuite seulement, tu débuggueras.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    od -c la_page.html | grep --color '\\r'

  7. #7
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Faire ça en shell n'est pas une bonne idée, mais bon, puisque tu poses la question, ton problème ne vient pas de la concaténation, mais des retours chariot qu'il faut supprimer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    descr=${nextLine//$'\r'}
    à condition que tu puisses t'écarter du posix comme l'a demandé N_BaH.

    Par ailleurs, avec la même réserve au niveau posix, remplace tes grep par des tests sur des regex, ça ira beaucoup plus vite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if [[ $line =~ '<div class="detailtopic">Description</div>' ]]if [[ $nextLine =~ '</td>' ]]
    Enfin, tu devrais intercaler des espaces dans tes concaténations, protéger la variable pour l'affichage final, et supprimer l'espace en trop à la fin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    description+="$descr "echo "${description:0:-1}"
    +++

    EDIT : Oups ! Il y a eu des choses de postées pendant que je rédigeais : tant pis, je laisse…

  8. #8
    Membre averti
    Homme Profil pro
    Chargé d'affaire
    Inscrit en
    Novembre 2015
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Chargé d'affaire

    Informations forums :
    Inscription : Novembre 2015
    Messages : 49
    Par défaut Extraordinaire !
    Fantastique.... Ma vie vient de changer.... Merci Balkani.
    Ce if [[ $line =~ ]] vient de changer ma vie... Adieu la perte de 20 secondes entre chaque test... Et dire que j'utilisais le grep depuis toujours...

    La solution pour la suppression du retour chariot a fonctionné immédiatement aussi.

    Deuxième lanterne... mais oui... Pourquoi j'utilise le shell ? Bah... parce que la dernière fois qu'on a du coder un truc du genre c'était à l'IUT et c'était en shell... Je me suis jamais posé la question de si c'était plus simple autrement... Si vous avez un langage à me recommander, je suis preneur... Je suppose que Python pourrait être bien ?

    N_BaH, pour le found -eq 1, je me suis relu... Effectivement... Je n'sais pas pourquoi j'ai pondu ça... ça m'a semblé plus clair en utilisant le if désormais.... Merci Flo pour les explication sur le retour chariot également....


    Merci pour votre extraordinaire coup de main ! =) Je continue en attendant.... J'essaye à présent de me log pour récupérer des infos accessible seulement logué... je suis sur la bonne voie pour le moment.

  9. #9
    Membre émérite Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 348
    Par défaut
    Je ne voulais pas tellement dire d'utiliser un autre langage, mais plutôt une commande appropriée, comme un parser html, ou bien avec sed comme Flodelarab en #3.

    Petite remarque concernant l'usage des regex en bash : en général, il est plus prudent de mettre la regex au préalable dans une variable, puis de l'utiliser dans le test (pour que ses caractères spéciaux soient bien interprétés, tout en supprimant les éventuels problèmes avec les espaces) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    regex='<div class="detailtopic">Description</div>'
    if [[ $line =~ $regex ]]
    Dans ce cas particulier, où il ne s'agit « pas vraiment » d'une regex, on aurait pu se contenter d'une simple reconnaissance de motifs bash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if [[ $line == *'<div class="detailtopic">Description</div>'* ]]

Discussions similaires

  1. [Batch] Comparaison de chaine de caractères dans une boucle for
    Par dark_vidor dans le forum Scripts/Batch
    Réponses: 3
    Dernier message: 19/10/2017, 16h00
  2. Concaténation de chaines de caractères dans une boucle
    Par nicolas823 dans le forum Shell et commandes GNU
    Réponses: 3
    Dernier message: 09/12/2013, 18h33
  3. Récupérer une chaine de caractère dans une page
    Par BrunS dans le forum Langage
    Réponses: 3
    Dernier message: 15/11/2005, 14h28
  4. [String]Recherche d'une chaine de caractères dans une autre
    Par Crazyblinkgirl dans le forum Langage
    Réponses: 3
    Dernier message: 29/07/2004, 11h51
  5. recherche d'une chaine de caractère dans une données text
    Par jdeheul dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 17/06/2004, 16h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo