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 :

remplacement via awk (jawk)


Sujet :

Shell et commandes GNU

  1. #1
    Membre régulier
    Inscrit en
    Mai 2007
    Messages
    183
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 183
    Points : 121
    Points
    121
    Par défaut remplacement via awk (jawk)
    Bonjour à tous.
    Ma problématique, c'est modifier un fichier sql via awk :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SET FOREIGN_KEY_CHECKS=0;
     
    CREATE TABLE `AUTOTASK` (
      `ID_AUTOTASK` varchar(30) NOT NULL,
      `var_name` varchar(30) NOT NULL,
      PRIMARY KEY  (`id_autotask`,`var_name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
     
    INSERT INTO `autotask` VALUES ('1HOUR_AUTOTASK.PHP', 'BASETIME');
    Je souhaite harmoniser tous les champs et les noms de table en minuscule. Concrêtement mettre en minuscule toutes les chaines avec la syntaxe `ABC` ou `_ABC` ou `A_BC` ou `ABC_`, etc

    Il parait que c'est simple avec l'outils awk (j'utilise une version java jawk qui répond exactement à la même syntaxe).

    Mon expression rationnelle fonctionne, j'y suis presque avec le script :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    { 
    if (gsub(/\`[A-Z,_]*\`/,tolower($0), $0)==1) {print $0;}
    else {print;}
    }
    Voici le résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SET FOREIGN_KEY_CHECKS=0;
    
    CREATE TABLE create table `autotask` ( (
        `id_autotask` varchar(30) not null, varchar(30) NOT NULL,
      `var_name` varchar(30) NOT NULL,
      PRIMARY KEY  (`id_autotask  primary key  (`id_autotask`,`var_name`)var_name`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
    INSERT INTO `autotask` VALUES ('1HOUR_AUTOTASK.PHP', 'BASETIME');
    Je constate que gsub m'insère la ligne entière (en rouge) au lieu de lu mot détecté. Je pense que mon print $0 ne doit pas être bon.

    Y a des connaisseurs qui peuvent m'aider ?

    Merci.

  2. #2
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut
    Bonjour,

    Voici une solution qui fonctionne, avec prise en compte de l'indentation (awk supprime normalement les blancs de début et de fin!). Cependant, les blancs multiples à l'intérieur d'une ligne sont réduits à un seul (on le voit à la ligne qui commence par PRIMARY KEY).
    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
    awk '
    {
        indent = match($0, /[^ ]/)
        for (i = 1; i < indent; i++)
        {
            printf " "
        }
        space = ""
        for (i = 1; i <= NF; i++)
        {
            if ($i ~ /^`[[:upper:]_]*`$/)
            {
                $i = tolower($i)
            }
            printf "%s%s", space, $i
            space = " "
        }
        printf "\n"
    }'
    La première boucle for ajoute autant de blancs qu'il y en avait (c'est l'indentation qui est replacée). Attention: s'il y a des tabulations, ça ne marche pas.
    La seconde boucle for écrit chaque ligne mot par mot et transforment ceux qui sont de la forme "lettres majuscules avec peut-être un '_'".

    Edit: Oups, erreur grossière, les mots ne sont pas obligatoirement séparés par des blancs... je vais revoir ma copie

  3. #3
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut
    Bin désolé pour cette première version foireuse, en voici une qui me semble bien plus correcte. Il n'y a plus de problème d'indentation ni de multiples blancs au milieu des lignes. Tout reste identique (sauf ce qui doit changer, bien sûr). De plus, il peut y avoir de multiples changements sur la même ligne, ça marche toujours. Enfin ça devrait...
    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
    awk '
    {
        line = $0
        do
        {
            first = match(line, /`[[:upper:]_]*`/)
            if (first == 0)
            {
                printf "%s\n", line
                next
            }
            second = first + match(substr(line, first + 1), /`/)
            printf "%s%s", substr(line, 1, first), tolower(substr(line, first + 1, second - first))
            line = substr(line, second + 1)
        } while (line != "")
    }'
    Bon, explications:
    first est l'index du ` qui ouvre un nom à changer, second est l'index du ` qui ferme ce nom. J'imprime tel quel le début de ligne, puis passe en minuscule le nom, et enfin retaille la ligne: il se peut qu'il y ait encore des changements dans cette ligne. Sinon, j'imprime le reste et passe à la ligne suivante.

    Y a moins de lignes et ça marche mieux .

  4. #4
    Membre régulier
    Inscrit en
    Mai 2007
    Messages
    183
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 183
    Points : 121
    Points
    121
    Par défaut
    Ma version JAWK ne semble pas accepter la même syntaxe des expressions rationnelle, j'ai donc juste modifié le regexp pour ma version:

    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
     
    {
        line = $0
        do
        {
            first = match(line, /\`[A-Z,_]*\`/)
            if (first == 0)
            {
                printf "%s\n", line
                next
            }
            second = first + match(substr(line, first + 1), /`/)
            printf "%s%s", substr(line, 1, first), tolower(substr(line, first + 1, second - first))
            line = substr(line, second + 1)
        } while (line != "")
    }
    .. et ça marche nickel !

    Merci et bravo !

    (c'était pas si simple que ça)

  5. #5
    Membre éclairé Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Points : 823
    Points
    823
    Par défaut
    Effectivement, l'interprétation des expressions régulières de jawk me semble bizarre:
    * POSIX donne plein de classes de caractères comme [:alnum:], [:blank:] ou [:punct:].
    * cette virgule devrait être interprétée comme le caractère , et pas comme un séparateur de champ.
    * le caractère ` ne devrait pas avoir besoin d'être échappé. D'ailleurs, il ne l'est pas à la 11e ligne: second = ... /`/)

    À partir du moment où l'on sait exactement ce qu'il faut faire, le codage devient simple (en général). J'espère que les explications sont suffisantes...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Sélection paragraphe via awk
    Par jolicare dans le forum Shell et commandes GNU
    Réponses: 13
    Dernier message: 30/07/2014, 10h59
  2. Réponses: 2
    Dernier message: 26/12/2013, 19h39
  3. remplacements via regexp
    Par sluke dans le forum Général Python
    Réponses: 6
    Dernier message: 09/09/2011, 12h27
  4. Chercher/remplacer via vba
    Par needlesurfer dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 27/05/2009, 13h03
  5. remplacement du awk en perl
    Par Avicen dans le forum Langage
    Réponses: 11
    Dernier message: 21/06/2007, 15h47

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