Forum Programmation.shell echanger deux mots avec expression rationnelle

Posté par (page perso) .
Tags : aucun
0
11
avr.
2006
je cherche à échanger deux mots avec une expression rationnelle. Je compte utiliser ceci avec sed (ou vi) dans un script.

toto et titi sont dans un bateau. titi tombe à l'eau.

doit par exemple être remplacé par : titi et toto sont dans un bateau. toto tombe à l'eau.

Actuellement je cherche un truc comme s/\(toto\) \(titi\)/\2 \1/g mais je n'y arrive pas. Merci de m'aider.
  • # exemple

    Posté par . Évalué à 1.

    ta syntaxe me parait bancale, t'as trouvé ça où ?

    pourquoi tu ne fait tout simplement pas : sed s/"mot_ancien"/"mot_nouveau"/g ?
  • # sed le glouton

    Posté par . Évalué à 2.

    L'expression rationnelle doit "coller" au texte à modifier.
    Avec '\(toto\) \(titi\)', ce n'est pas le cas : ce qu'il y a entre '\(toto\)' et '\(titi\)', c'est-à-dire ' ' (un simple espace), ne peut pas correspondre pas à 'et '.

    Une solution possible : sed 's/\(toto\)\(.*\)\(titi\)/\3\2\1/'

    Oui mais... ton exemple est ambigü, et avec sed, ça donnera ça :
    titi et titi sont dans un bateau. toto tombe à l'eau.

    Pas certain que ce soit ce que tu veux. C'est parce que l'opérateur '*' est glouton (greedy en anglais). En perl, il y a l'opérateur '*?' pour avoir le comportement opposé. Je crois qu'il n'y a d'équivalent en sed, à moins d'écrire quelques horreurs comme :

    sed 's/\(toto\)\(\([^t]\|\(t\([^i]\|\(i\([^t]\|t[^i]\)\)\)\)\)*\)\(titi\)/\8\2\1/'
  • # c'est pas trop dur

    Posté par (page perso) . Évalué à 3.

    Le seul probleme, c'est que tu dois eviter de modifier les "toto" que tu viens d'ecrire a la place des "titit", et ne remplacer que les "toto" originaux.
    Il suffit de passer par un mot magique (par exemple, "papaille", qui n'est pas dans ton document) pour fire la difference

    du coup:

    echo "titi et toto sont dans un bateau: titi tombe a l'eau"
    | sed -e 's/titi/papaille/g' -e 's/toto/titi/g' -e 's/papaille/toto/g'

    donne ce que tu attends
  • # avec awk:

    Posté par . Évalué à 3.


    echo " toto et titi sont dans un bateau. titi tombe à l'eau." | \
    awk '
    {
    for(i=1;i<=NF;i++) {
    if ($i=="titi") {
    $i="toto"
    }
    else {
    if ($i=="toto") {
    $i="titi"
    }
    }

    }
    print $0

    }
    '


    Je suis sur qu'il y a moyen de mieux faire.
  • # merci à tous

    Posté par (page perso) . Évalué à 1.

    effectivement ce problème n'était pas aussi simple, je resté persuadé qu'il pouvait y avoir une expression régulière simple.
    il faut de toute facon soit une condition if .... soit un troisième mot (une autre variable pour l'échange)
    quand à la ligne s/\(toto\) \(titi\)/\2 \1/g évidemment c'est bancale, mais je pensais juste à réutilier avec \1 et \2.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.