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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Mai 2007
    Messages
    183
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 183
    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 émérite 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
    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 émérite 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
    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 confirmé
    Inscrit en
    Mai 2007
    Messages
    183
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 183
    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 émérite 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
    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, 09h59
  2. Réponses: 2
    Dernier message: 26/12/2013, 18h39
  3. remplacements via regexp
    Par sluke dans le forum Général Python
    Réponses: 6
    Dernier message: 09/09/2011, 11h27
  4. Chercher/remplacer via vba
    Par needlesurfer dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 27/05/2009, 12h03
  5. remplacement du awk en perl
    Par Avicen dans le forum Langage
    Réponses: 11
    Dernier message: 21/06/2007, 14h47

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