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 :

[Shell] Traitement du texte d'un fichier


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut [Shell] Traitement du texte d'un fichier
    Bonjour,

    Je souhaiterais écrire un script qui me permettrai de lire un fichier, extraire un contenu spécifique et le mettre dans un autre fichier.

    Exemple :
    fichier source :
    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
    [[ Groupe 1 ]]
    name = "Elinux"
    classe = "1"
     
    [[ Groupe 2 ]]
    name = "Elinux_2"
    classe = "2"
     
    [[ Groupe 3 ]]
    name = "Elinux_3"
    classe = "2"
     
    [[ Groupe 4 ]]
    name = "Elinux_4"
    classe = "4"
    Je souhaiterais mettre dans le fichier de sortie que les informations des classe = "2" !
    Résultat attendu dans le fichier de sortie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    [[ Groupe 2 ]]
    name = "Elinux_2"
    classe = "2"
     
    [[ Groupe 3 ]]
    name = "Elinux_3"
    classe = "2"
    Je commence à faire du script, je trouve sur google l'utilisation de la fonction "sed", mais je n'ai pas réussi !
    Je sais déjà comment lire un fichier et comment copier le résultat dans un autre, mais le plus important, je ne sais pas faire haha.


    Auriez-vous des indications ?

    Merci

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

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

    Une solution awk simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ awk 'function aff(){if (gr==1) print txt;txt="";} /classe = "2"/{gr=1;} /\[\[/{aff();gr=0;} {txt=txt""((txt=="")?"":"\n")""$0;} END{aff();}' fichier.txt                                                                                                                  
    [[ Groupe 2 ]]
    name = "Elinux_2"
    classe = "2"
     
    [[ Groupe 3 ]]
    name = "Elinux_3"
    classe = "2"
    Une solution awk plus tranchante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ awk -vRS='\\[\\[' 'NR==1{next;} /classe = "2"/{print "[["$0;}' fichier.txt 
    [[ Groupe 2 ]]
    name = "Elinux_2"
    classe = "2"
     
     
    [[ Groupe 3 ]]
    name = "Elinux_3"
    classe = "2"

  3. #3
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut
    Hello,

    Merci pour la solution.
    Je ne sais pas si c'est la même chose, mais je souhaiterais faire ça en shell (sh).

    Est-ce bien la même chose ?

    Merci.

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 288
    Par défaut
    Si c'est pour l'école, cela n'ira pas. Si c'est pour la vie, ça marchera. Si tu veux le faire en bash, j'imagine que tu utiliseras un algorithme similaire à la première proposition.

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par Elinux Voir le message
    Je commence à faire du script, je trouve sur google l'utilisation de la fonction "sed", mais je n'ai pas réussi !
    ...
    Je ne sais pas si c'est la même chose, mais je souhaiterais faire ça en shell (sh).
    Pour préciser la réponse/question de Flodelarab, veux-tu le faire:
    a) en langage de commande (comme un script shell) ?
    b) en shell pur, genre bash ?
    c) en shell pur, genre sh ?

    Tu veux probablement dire (a) car, dans ton message précédent, tu évoques l'utilisation de "sed" qui, comme "awk", est un utilitaire annexe (avec son propre langage).

    Ces 2 commandes sont parfaitement acceptables dans un script shell.

    Sinon, il faut écrire un script shell pur qui lit le fichier ligne à ligne, enregistre chaque ligne "groupe" et chaque ligne "name" en mémoire et imprime les lignes enregistrées dès qu'il rencontre une ligne "classe" avec "2".

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut
    Bonjour Flodelarab,
    Oui je comprends, je vais repartir de ce que vous m'avez donné.
    Je vous partagerai le résultat ici !

    Bonjour jack-ft,
    Je suis un peu perdu en lisant votre message, je pense que je dois lire plus, pour comprendre la différence entre bash et sh !
    A l'école, ils me demandent de faire un .sh pour une exécution/modification plus facile du script, donc j'aurai dis la réponse "c"

    Merci à tous les deux.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 653
    Par défaut
    un .sh, c'est très vague !
    à peu près tous les scripts shell peuvent avoir une extension .sh (voire tous les fichiers, sur Linux les applications s'en foutent : elles feront ce qui est indiqué soit dans l'en-tête, soit dans le shebang).

    et ça ne résout pas le problème, un script .sh peut être un script
    • 100% POSIX (respectant strictement (ni plus, ni moins) la norme de ce qu'un shell doit pouvoir proposer)
    • 99% bash, ksh, zsh (attention: csh n'est pas POSIX, et ne devrait pas accepter d'extension .sh, mais .csh pour indiquer immédiatement ce dont il s'agit), pas de commandes externes (à moins de ne vraiment pas avoir le choix : cp n'existe pas en commande interne)
    • accepter des commandes externes (à opposer aux commandes internes du shell utilisé, voire des langages (awk, python, perl,... , php ())..., qui peuvent parfois être remplacés avec profit par des commandes internes (commandes ou développements POSIX, ou extensions))
    • mixte : compatible POSIX (avec des extensions possibles), avec des commandes externes (parfois, on n'a pas le choix voir plus haut ).


    et si mÔssieu le péda[nt]gogue n'est pas content, tu me l'envoies. On va lui expliquer. j'en salive d'avance.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  8. #8
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par Elinux Voir le message
    A l'école, ils me demandent de faire un .sh pour une exécution/modification plus facile du script, donc j'aurai dis la réponse "c"
    Euh... Pour commencer, il y a plein de shells différents (sh, ksh, csh, bash, tcsh, zsh, etc.), chacun avec ses spécificités. Pour plus d'infos, voir par exemple https://fr.wikipedia.org/wiki/Shell_Unix.

    Un des plus utilisés, surtout dans l'environnement linux est le "bash" (qui est en gros une sorte de réminiscence très améliorée du vieux shell originel "sh").

    Sur une version récente d'un mac, ce sera "zsh", mais le "bash" y est également accessible.

    Si on te demande de "faire un script pour une exécution/modification plus facile", c'est probablement par opposition à un programme compilé en C ou autre.

    Dans ce cas, les instructions awk fournies par Flodelarab conviennent tout à fait et peuvent être mises telles quelles dans un script shell.

    En gros, si tu es sous linux, il te suffit juste de mettre ces 2 lignes dans un fichier "mon_script.sh":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #!/bin/bash
    awk 'function aff(){if (gr==1) print txt;txt="";} /classe = "2"/{gr=1;} /\[\[/{aff();gr=0;} {txt=txt""((txt=="")?"":"\n")""$0;} END{aff();}'
    de modifier les droits d'exécution du script en faisant une seule fois chmod +x ./mon_script.sh, puis de lancer son exécution en faisant, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ./mon_script.sh < fichier.txt > fichier-classe-2.txt
    Plus tard, quand tu voudras, par exemple, passer le "2" en paramètre du script pour pouvoir le remplacer par une valeur choisie par l'utilisateur, il te faudra juste faire quelques petites modifications dans le script.


    D'un autre côté, tu dis que tu sais déjà lire un fichier et écrire un fichier (en bash, j'imagine). Donc, si tu as l'impression que c'est ce qui est attendu de toi, alors il vaut probablement mieux écrire le script en pur bash... en suivant l'algorithme dont Flodelarab et moi-même avons parlé.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 653
    Par défaut
    si tu es sous linux, il te suffit juste de mettre ces 2 lignes dans un fichier "mon_script.sh":
    heu... ça c'est un script awk. Je ne vois pas une seule commande shell (le shebang peut-être...).
    un "script" shell qui exécute un autre langage, c'est un "wrapper".


    si tu es sous linux
    si tu es sous linux, alors tu es une machine!
    l'opérateur est au-dessus de tout ça. cf. "un nain sur un géant" versus "un nain sous un géant" (façon suppositoire).
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  10. #10
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    heu... ça c'est un script awk. Je ne vois pas une seule commande shell (le shebang peut-être...).
    un "script" shell qui exécute un autre langage, c'est un "wrapper".
    Et si on met un pipe, ça fait un script shell, non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #!/bin/bash
    cat $1 | awk 'function aff(){if (gr==1) print txt;txt="";} /classe = "2"/{gr=1;} /\[\[/{aff();gr=0;} {txt=txt""((txt=="")?"":"\n")""$0;} END{aff();}'

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 653
    Par défaut

    HÉRÉTIQUE !!! AU BÛCHER !

    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 288
    Par défaut
    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
    $ cat transfo.awk 
    #!/usr/bin/awk -f
     
    function aff()
    {
            if (gr==1) 
                    print txt;txt="";
    } 
     
    /classe = "2"/{
            gr=1;
    } 
     
    /\[\[/{
            aff();
            gr=0;
    } 
     
    {
            txt=txt""((txt=="")?"":"\n")""$0;
    } 
     
    END{
            aff();
    }
    $ chmod +x transfo.awk
    $ ./transfo.awk fichier.txt                                                                  
    [[ Groupe 2 ]]                                                                                                         
    name = "Elinux_2"                                                                                                      
    classe = "2"                                                                                                           
     
    [[ Groupe 3 ]]                                                                                                         
    name = "Elinux_3"
    classe = "2"

  13. #13
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut
    Hello,

    Merci pour vos réponses !

    Flodelarab Le script fonctionne bien, mais je n'ai pas compris comment ça marche ! haha
    Plus précisément ces deux lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    txt=txt""((txt=="")?"":"\n")""$0;
    (Merci pour le cours awk N_BaH)

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 288
    Par défaut
    Pour la première ligne que tu cites, le découpage est terrible. Mais c'est à moitié ma faute aussi, car je n'ai pas séparé, au moment de l'expansion d'une seule ligne en plusieurs lignes.
    Ce n'est pas print txt;txt="";, mais if (gr==1) print txt;, d'une part, et txt="";, d'autre part.
    En français, si le drapeau gr est égal à 1, alors on affiche txt qui contient le texte du groupe précédent. Et dans tous les cas, on vide la variable txt, puisqu'on commence un nouveau groupe.

    La deuxième ligne que tu cites est la concaténation de la ligne actuelle au texte déjà en mémoire. ( (condition) ? si oui : sinon) est un opérateur ternaire. Il renvoie la valeur après le point d'interrogation si la condition est vraie, et la valeur après les deux points si la condition est fausse. Ici l'opérateur ternaire permet de remettre une fin de ligne.

  15. #15
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut
    Cette ligne aussi, je n'ai pas réussi à la comprendre !

    Aussi, j'ai remarqué que si mon texte contiens des " au milieu, celui-ci le dérange, et le programme ne comprends pas qu'il fais parti de la chaine de caractère. J'observe la même chose pour le crochet [ si je met :
    /classe = ["2"]/ , dans ce cas il ne comprends pas que le crochet appartient à la chaine de caractère.
    J'ai essayé de mettre une variable du genre var="/classe = ["2"]/", mais cela ne fonctionne pas.

    J'ajoute à ça si mes classe = ["2"] ont une suite que je veux ignorer (exemple : classe = ["2_bleue"], classe = ["2_rouge"]) et que moi je veux toujours afficher les classe = ["2_*"].
    --> Est ce que l' * est acceptée dans ce cas la ? (je vais tester cela)

    Exemple du fichier (avec plus d'infos) à traiter :
    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
    [[ Groupe 1 ]]
    name = "Elinux"
    classe = ["1_noire"]
    num = 22 
     
    [[ Groupe 2 ]]
    name = "Elinux_2"
    classe = ["2_bleue"]
    num = 12 
     
    [[ Groupe 3 ]]
    name = "Elinux_3"
    classe = ["2_rouge"]
    num = 15
     
    [[ Groupe 4 ]]
    name = "Elinux_4"
    classe = ["4_orange"]
    num = 9

  16. #16
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Pour la première ligne que tu cites, le découpage est terrible. Mais c'est à moitié ma faute aussi, car je n'ai pas séparé, au moment de l'expansion d'une seule ligne en plusieurs lignes.
    Ce n'est pas print txt;txt="";, mais if (gr==1) print txt;, d'une part, et txt="";, d'autre part.
    En français, si le drapeau gr est égal à 1, alors on affiche txt qui contient le texte du groupe précédent. Et dans tous les cas, on vide la variable txt, puisqu'on commence un nouveau groupe.

    La deuxième ligne que tu cites est la concaténation de la ligne actuelle au texte déjà en mémoire. ( (condition) ? si oui : sinon) est un opérateur ternaire. Il renvoie la valeur après le point d'interrogation si la condition est vraie, et la valeur après les deux points si la condition est fausse. Ici l'opérateur ternaire permet de remettre une fin de ligne.
    Je vous remercie pour ces explications, je comprends mieux le programme !
    Mais les " et [ m'intriguent toujours.

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 288
    Par défaut
    Ce n'est pas une chaîne de caractères, mais une expression rationnelle (regular expression = regex). Renseigne-toi sur les regex.

  18. #18
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2018
    Messages
    73
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2018
    Messages : 73
    Par défaut
    Merci pour les indications !

    Alors, je ne sais pas je me trompe, mais j'ai compris que dans mon cas, il faut que j'utilise le POSIX mnemonic [:punct:] sachant que je considère le crochet [ comme un caractères de ponctuation.

    J'ai donc utilisé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /[:punct:classe = ["2_"]/
    L'exécution m'affiche tout le contenu du fichier ! Donc quelque chose m'échappe.

  19. #19
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par Elinux Voir le message
    Cette ligne aussi, je n'ai pas réussi à la comprendre !

    Il faut savoir qu'une chaine entre "/", comme /une_chaine/, indique à awk que, lorsque la ligne courante du fichier contient cette chaîne, awk doit effectuer les actions qui suivent.

    Flodelarab veut demander à awk de repérer les lignes qui contiennent 2 crochets ouvrants, c'est-à-dire les lignes comme [[ Groupe 3 ]] correspondant à l'en-tête d'un nouveau groupe, auquel cas il appelle la fonction aff qui imprime le groupe précédent dans le cas où gr==1 puis vide la variable txt afin de pouvoir la remplir de nouveau avec les données du groupe suivant.

    Pour repérer une ligne avec 2 crochets ouvrants, on pourrait croire qu'il suffirait de faire la recherche /[[/, mais le crochet est un caractère spécial pour awk et les expressions régulières en général. Pour spécifier qu'on cherche ce caractère sans son caractère spécial, il faut le protéger (le "quoter") avec un backslash (barre oblique inversée). Ainsi, dans une expression régulière, \[ représente une occurrence du crochet ouvrant. EN conséquence, /\[\[/ représente donc la recherche de 2 crochets ouvrants consécutifs.

    Imho, personnellement, j'aurais essayé de restreindre le plus possible la possibilité de faux positifs, comme des occurrences de [[ ailleurs (si le format du fichier devait changer).

    J'aurais donc écrit /^\[\[ Groupe [0-9]+ \]\]$/ (ou quelque chose d'approchant (car non testé (donc non validé) et le crochet fermant n'a peut-être pas besoin d'être quoté)).


    Pour info, txt="" veut dire mettre une chaine de caractères vide dans la variable txt.

    Et la ligne txt=txt""((txt=="")?"":"\n")""$0; pourrait se réécrire sans l'opérateur ternaire en:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (txt!="")
        txt=txt"\n"
    txt=txt""$0
    qui se lit comme suit: si le contenu de la variable txt n'est pas une chaine vide, alors lui ajouter une fin de ligne, puis lui ajouter le contenu de la ligne courante (sans fin de ligne).

    L'expression txt""$0 indique la concaténation de 3 chaines: le contenu de la variable txt, une chaine vide et le contenu de la ligne courante.

    La chaine vide du milieu est la manière standard d'indiquer à awk qu'il faut faire une concaténation.

    (awk n'a pas d'opérateur de concaténation, comme "+" en python, par exemple. On ne peut donc pas écrire txt = txt + $0 ni txt += $0)

  20. #20
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 102
    Par défaut
    Citation Envoyé par Elinux Voir le message
    J'ajoute à ça si mes classe = ["2"] ont une suite que je veux ignorer (exemple : classe = ["2_bleue"], classe = ["2_rouge"]) et que moi je veux toujours afficher les classe = ["2_*"].
    --> Est ce que l' * est acceptée dans ce cas la ? (je vais tester cela)
    Dans une regexp, le caractère "*" indique que le truc précédent peut être présent en n'importe quel nombre d'exemplaires.

    Dans ton cas, le truc précédent est le caractère "_", mais, comme tu n'as pas quoté le premier crochet ouvrant, la regexp repère les crochets et veut dire "un caractère quelconque parmi le guillemet, le chiffre 2, l'underscore _ et l'étoile *".

    Si tu veux dire n'importe quel caractère en nombre quelconque, il faut utiliser la regexp .* (voir ma version du script de Flodelarab à la fin) car, dans une regexp, le point . veut dire n'importe quel caractère (sauf un retour à la ligne).

    Exemple du fichier (avec plus d'infos) à traiter :
    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
    [[ Groupe 1 ]]
    name = "Elinux"
    classe = ["1_noire"]
    num = 22 
     
    [[ Groupe 2 ]]
    name = "Elinux_2"
    classe = ["2_bleue"]
    num = 12 
     
    [[ Groupe 3 ]]
    name = "Elinux_3"
    classe = ["2_rouge"]
    num = 15
     
    [[ Groupe 4 ]]
    name = "Elinux_4"
    classe = ["4_orange"]
    num = 9
    Faudrait voir à éviter de changer trop souvent le format du fichier car ça augmente le travail des bénévoles...

    Citation Envoyé par Elinux Voir le message
    Alors, je ne sais pas je me trompe, mais j'ai compris que dans mon cas, il faut que j'utilise le POSIX mnemonic [:punct:] sachant que je considère le crochet [ comme un caractères de ponctuation.

    J'ai donc utilisé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /[:punct:classe = ["2_"]/
    L'exécution m'affiche tout le contenu du fichier ! Donc quelque chose m'échappe.
    Comme je l'ai indiqué précédemment, le crochet ouvrant doit être quoté (mais pas le fermant (après vérification et validation)). Tu as le droit de le considérer comme un caractère de ponctuation si ça te fait plaisir, mais je doute que awk soit du même avis. Il faut donc mettre /^classe = \["2_/ ou bien /^classe = \["2_.*"]$/, pour plus de sécurité, avec le fameux .* dont j'ai parlé plus haut.

    Voici le script que j'ai testé:

    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
    #!/usr/bin/awk -f
     
    function aff()
    {
            if (gr==1) print txt;
            txt="";
    }
     
    /^classe = \["2_.*"]$/{
            gr=1;
    }
     
    /^\[\[ Groupe [0-9]+ ]]$/{
            aff();
            gr=0;
    }
     
    {
            if (txt!="") txt=txt"\n"
            txt=txt""$0
    }
     
    END{
            aff();
    }

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Korn shell: remplir un tableau à partir de fichier texte
    Par julie26000 dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 18/01/2014, 13h24
  2. besoin d'aide pour un script shell extrayant les données d'un fichier texte ou un fichier log
    Par haithem20080 dans le forum Applications et environnements graphiques
    Réponses: 7
    Dernier message: 15/03/2010, 14h10
  3. Réponses: 12
    Dernier message: 18/02/2009, 15h07
  4. [Shell] Traitement de fichier
    Par salsero1 dans le forum Linux
    Réponses: 5
    Dernier message: 27/06/2008, 11h28
  5. traitement texte d'un fichier
    Par sos dans le forum C
    Réponses: 6
    Dernier message: 15/06/2007, 14h45

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