J'ai vraiment du mal avec sed....

Résolu
rebonjour,

je voudrait avec sed remplacer
if_lt r4.x, c0.b 
par
IF LT.x

sachant que x peut etre dautre lettre donc par exemple si savais
if_lt r4.z, c0.b 
ce soit remplacé par
IF LT.z

au mieux j'aimerais que sed me trouve les "if_", recupere les deux caracteres suivant (lt, gt ,en ,eg) pour que si sed trouve
if_gt r4.w, c0.b 
ce soit remplacé par
IF GT.w

j'ai presque reussi mais c'est pas ça ...

à l'aide jipicy :)

ps : quelle est la fonction pour remplacer une ligne entiere et pas seulement les occurence que sed trouve?

Configuration: Linux
Firefox 2.0.0.6

21 réponses

  1. $ A='if_lt r4.x, c0.b'
    
    $ echo $A
    if_lt r4.x, c0.b
    
    $ echo $A |sed -r  's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/'
    IF LT.x
    
    $ cat test.psh
    if_lt r4.x, c0.b
    
    $ sed -r -i.orig 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' test.psh
    
    $ cat test.psh
    if_lt r4.x, c0.b
    
    $ cat test.psh.orig
    if_lt r4.x, c0.b
    
    $ sed -r -i 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' test.psh
    
    $ cat test.psh
    if_lt r4.x, c0.b
    
    $ sed -r 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' test.psh > retest.psh
    
    $ cat retest.psh
    if_lt r4.x, c0.b
    
    
    

    j'y comprend rien , pourquoi ça marche chez vous et pas chez moi ???
    par contre
    $ echo 'if_lt r4.x, c0.b' > rere
    
    $ cat rere
    if_lt r4.x, c0.b
    
    $ sed -r -i 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' rere
    
    $ cat rere
    IF LT.x
    
    

    etrange....
    1
    1. Modérateur
      mets ton fichier sur cjoint.com pour voir ce qui ne vas pas
      tu peux le compresser avant de le mettre
      1
      1. Modérateur
        Re-

        Si la structure du motif est toujours la même, à savoir :
        if underscore 2 caractères espace 2 caractères 1 point 1 caractère 1 virgule etc..."
        alors ça devrait faire l'affaire :
        sed 's/if_../\U&/;s/_/ /;s/\(.....\)...\(..\).*/\1\2/'
        Concernant ta demande de remplacement d'une ligne entière voir :
        sed insertion de texte#echanger une ligne avec c

        ;-))
        0
        1. merci de ton aide

          cependant ça marche pas vraiment

          plusieurs truc
          dans mon script, ma ligne
          sed -i -e '/^[ ]*#\|^$\|^\n*$/! {/if_.. r\([0-9]\+\)/i\ADD CC, r\1}' $file$tmp1

          ne fonctionne pas , sed me renvoie
          sed: -e expression n°1, caractère 0: `{' non refermée

          si je retire ses accolades il me dit
          sed: -e expression n°1, caractère 34: commande inconnue: `/'
          

          cette ligne devrait normalement me rajouter "ADD CC, r+un_chiffre" au dessus de toute les occurrences de "if_lt r8.z, c0.b" ou "if_en r8.x, d0.x"par exemple

          ensuite
          sed 's/if_../\U&/;s/_/ /;s/\(.....\)...\(..\).*/\1\2/'
          plante mon script s'arrete et c'est tout ...
          apparement "sed 's/if_../\U&/;s/_/ /;" passe bien c'est le troisieme partie "s/\(.....\)...\(..\).*/\1\2/" qui a du mal

          merci d'avance
          0
          1. Modérateur
            Ben chez moi ça passe bien, à part la référence arrière dans la 1ère partie :
            [tmpfs]$ A='if_lt r4.x, c0.b\nif_gt r4.w, c0.b'
            
            [tmpfs]$ echo -e "$A"
            
            if_lt r4.x, c0.b
            if_gt r4.w, c0.b
            
            [tmpfs]$ echo -e "$A" | sed '/if_.. r\([0-9]\+\)/i\ADD CC, r\1'
            
            ADD CC, r1
            if_lt r4.x, c0.b
            ADD CC, r1
            if_gt r4.w, c0.b
            
            [tmpfs]$ 
            Et pour la seconde partie :
            [tmpfs]$ A='if_lt r4.x, c0.b\nif_gt r4.w, c0.b'
            
            [tmpfs]$ echo -e "$A"
            
            if_lt r4.x, c0.b
            if_gt r4.w, c0.b
            
            [tmpfs]$ echo -e "$A" | sed 's/if_../\U&/;s/_/ /;s/\(.....\)...\(..\).*/\1\2/'
            
            IF LT.x
            IF GT.w
            
            [tmpfs]$
            Donc je sais pas ce qui cloche, peut être que l'expression ne matche pas exactement ce qu'il faut en fonction du fichier original... moi je ne te propose que des bribes de code en fonction des éléments que tu me fournis.

            ;-))
            0
        2. autrement j'ai essaye ça qui me donne presque ce que je veut :
          sed -i -e '/^[ ]*#\|^$\|^\n*$\|^\!\!ARBfp/! {s/\<if_.. r\([0-9]\+\)\>/ADD CC, r\1\nIF LT/}' $file

          sauf que au niveau de la fin de la ligne ("...\nIF LT/}' ...") je voudrait qu'il ne mette pas seulement LT mais si c'est if_en qu'il me mette EN.
          et aussi qu'il me supprime ce qui suit le IF LT.x.
          le mieux serait qu'il me remplace la ligne "if_lt r4.x, c0.b " par "ADD CC, r4\nIF LT.x" ( d'ou mon ps au premier post) ou un autre exemple, qu'il me remplace la ligne "if_en r18.z, c8.b " par "ADD CC, r18\nIF EN.z"
          0
          1. effectivement quand je retire /^[ ]*#\|^$\|^\n*$/! pour la ligne sed -i -e '/^[ ]*#\|^$\|^\n*$/! /if_.. r\([0-9]\+\)/i\ADD CC, r\1' $file ça fonctionne . le problème viens donc de ce /^[ ]*#\|^$\|^\n*$/! qui me filtre tout le code commenté
            ce qui est bizarre c'est que je l'utilise dans tout mes autres sed et il fonctionne bien

            ....j'avais pas vu qu'il me mettait 1 partout à la place de 4 dans ton exemple , mais la commande du post juste au dessus pourrait faire l'affaire si je peut récupérer le deux caractère après le if_ pour la réutiliser en majuscule, et si il me faisait une substitution de la ligne plutôt que des caractères
            0
            1. Modérateur
              Tiens essaie ça à la place :
              [tmpfs]$ A='if_lt r4.x, c0.b\nif_gt r5.w, c0.b'
              
              [tmpfs]$ echo -e "$A"
              
              if_lt r4.x, c0.b
              if_gt r5.w, c0.b
              
              [tmpfs]$ echo -e "$A" | sed '/if_.. r\([0-9]\+\).*/{h;s//ADD CC, r\1/;G}'
              
              ADD CC, r4
              if_lt r4.x, c0.b
              ADD CC, r5
              if_gt r5.w, c0.b
              
              [tmpfs]$
              ;-))
              0
              1. cool ,
                pour le ADD CC, r+le_nombre, c'est bon

                maintenant je suis enbetter encore pour 2 choses

                1) comment concatener les filtres "/if_/" et "/^[ ]*#\|^$\|^\n*$/!" ???
                2) pour la commande "sed 's/if_../\U&/;s/_/ /;s/\(.....\)...\(..\).*/\1\2/'" elle fonctionne uniquement si r est suivi d'un chiffre , ça ne fonctionne pas avec un nombre ( c'est ok avec 5 par exemple mais pas avec 19)
                0
                1. Modérateur
                  1) comment concatener les filtre "/if_/" et "/^[ ]*#\|^$\|^\n*$/!" ???
                  sed '/^[ ]*#\|^$\|^\n*$/! {/if_/ {...}}'

                  Pour le 2) je cale sur un problème de regex qui me fait carrément #*?!$ ;-[

                  Soit la variable :
                  $ echo -e "$A"
                  if_lt r4.x, c0.b
                  if_gt r5.w, c0.b
                  Soit la regex suivante (la partie en gras, correspondant à la référence arrière "3", donc 2 caractères à matcher) :
                  $ echo -e "$A" | sed '/if_.. r\([0-9]\+\).*/{s/if_../\U&/;s/_/ /;s/\(.....\)\( .*[^\.]\.\)\(..\).*/\1.\3/}'
                  
                  IF LT.x,
                  IF GT.w,
                  Qui marche très bien puisqu'elle me renvoie bien une lettre et la virgule qui suit.

                  Par contre la même en demandant uniquement la lettre sans la virgule (donc un caractère) :
                  $ echo -e "$A" | sed '/if_.. r\([0-9]\+\).*/{s/if_../\U&/;s/_/ /;s/\(.....\)\( .*[^\.]\.\)\(.\).*/\1.\3/}'
                  
                  IF LT.b
                  IF GT.b
                  Me renvoie le dernier caractère sur la ligne !!!??? Whyyyyyyyy ??????

                  lami20j si tu passes par là, tu seras plus que le bienvenu ;-)))
                  Merci d'avance.
                  0
                  1. Modérateur
                    Salut,

                    il ne faut pas oublier la gourmandise du quantificateur *
                    avec [a-z]$ à la fin de regex j'oblige de reconnaître un caractère alpha à la fin, sinon la regex avale tout et affiche la dernière lettre
                    Voilà.
                    # A='if_lt r4.x, c0.b\nif_gt r5.w, c0.b'
                    # echo -e $A |sed '/if_.. r\([0-9]\+\).*[a-z]$/{s/if_../\U&/;s/_/ /;s/\(.....\)\( .*[^\.]\.\)\(.\).*[a-z]$/\1.\3/}'
                    IF LT.x
                    IF GT.w
                    voir aussi ma version
                    # A='if_lt r4.x, c0.b\nif_gt r5.w, c0.b'
                    # echo -e $A | sed -r 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/'
                    IF LT.x
                    IF GT.w

                    0
                    1. Modérateur
                      Merci beaucoup ;-))

                      Mais ça ne m'explique pas pourquoi avec "\(..\)" ça marche et pas avec "\(.\)" ?!
                      Même si je sais que les regex sont gourmandes.
                      0
                  2. merci beaucoup à vous deux

                    un dernier truc que je pige pas : les deux commande sed donnée par Lami fonctionne très bien dans un shell , seulement, dès que je les insère dans mon script ben elle ne font rien....
                    voici comment je les ai noté toutes deux dans le script :
                    sed -i -e '/^[ ]*#\|^$\|^\n*$/! {/if_.. r\([0-9]\+\).*[a-z]$/{s/if_../\U&/;s/_/ /;s/\(.....\)\( .*[^\.]\.\)\(.\).*[a-z]$/\1.\3/}}' $file
                    
                    sed -i -r 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' $file
                    0
                    1. Modérateur
                      Mais ça ne m'explique pas pourquoi avec "\(..\)" ça marche et pas avec "\(.\)" ?!
                      C'est toute à fait normal que ça ne marche pas avec "\(.\)"

                      Prenons notre exemple
                      A='if_lt r46.x, c0.b\nif_gt r5.w, c0.b'

                      Cas "\(..\)"
                      Ici ça marche. Pourquoi?

                      Avant tu as \.\)
                      Ce qui veut dire qu'après un point tu cherche un caractère quelconque suit d'un autre caractère et ensuite .* jusqu'à la fin
                      Ben justement .* avale tout après .. donc après le 1er point suit d'un caractère (dans ce cas x) puisque après b il n'y a rien

                      Cas "\(.\)"

                      Avant tu as \.\)
                      Dans ce cas tu demande qu'après un caractère quelconque la regex exécute .*, mais tu as oublié peut être que .* réussi toujours donc en ce cas la regex ce contente avec rien (* - rien, un, combien tu peux)
                      Donc le b (le dernière caractère sera reconnu, et ensuite .* se content avec rien.

                      Tu diras que c'est contradictoire avec la gurmandise citée et evoquée autant de fois.
                      Mais c'est normal.
                      Au début .* avale tout (mais ça tu ne le vois pas) et ensuite sous contrainte * est obligé de céder autant de caractères pour que la regex réussisses.
                      Dans ce cas la regex cède le b, et c'est suffisant pour la réusite globale de la regex.

                      Je ne sais pas si j'était assez clair.
                      0
                      1. Modérateur
                        Cas "\(..\)"
                        Ici ça marche. Pourquoi?

                        Avant tu as \.\)
                        Ce qui veut dire qu'après un point tu cherche un caractère quelconque suit d'un autre caractère et ensuite .* jusqu'à la fin
                        Ben justement .* avale tout après .. donc après le 1er point suit d'un caractère (dans ce cas x) puisque après b il n'y a rien


                        Ben non justement, le premier point représente le "x" et le second la virgule, et donc là ça marche.

                        Cas "\(.\)"

                        Avant tu as \.\)
                        Dans ce cas tu demande qu'après un caractère quelconque la regex exécute .*, mais tu as oublié peut être que .* réussi toujours donc en ce cas la regex ce contente avec rien (* - rien, un, combien tu peux)
                        Donc le b (le dernière caractère sera reconnu, et ensuite .* se content avec rien.


                        Ben justement c'est ce qu'elle ne fait pas et je comprends par pourquoi malgré tes explications. Pourquoi elle ne retient pas ce caractère quelconque (normalement le "x") ?

                        Surement que c'est moi qui ai du mal à comprendre, mais je voudrai bien savoir quand même ;-))
                        0
                        1. truc bizarre
                          lorsque le lance le sed comme le fait Lami dans le shell (post 9) ça fonctionne
                          par contre lorque je fait dans le shell " sed -i -r -e '/^[ ]*#\|^$\|^\n*$/! s/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' mon_fichier " ben ça marche pas

                          exemple qui marche
                          $ echo -e $A | sed -r -e '/^[ ]*#\|^$\|^\n*$/! s/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/'
                          IF LT.x
                          IF GT.w
                          


                          exemple qui marche pas
                          $ sed -i -r -e '/^[ ]*#\|^$\|^\n*$/! s/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' mon_fichier
                          $ nano mon_fichier
                          
                          if_lt r19.x, c0.z;                # 0, 001
                          
                          0
                          1. Modérateur
                            Surement que c'est moi qui ai du mal à comprendre, mais je voudrai bien savoir quand même ;-))
                            Peut être c'est moi qui a mal expliqué.
                            Regarde une explication avec des exemples :
                            root@debian:~# A='if_lt r46.x, c0.b'
                            root@debian:~# echo "$A"
                            if_lt r46.x, c0.b
                            root@debian:~# echo "$A" | sed 's/\(.....\)\( .*[^\.]\.\)\(.\).*/\1/'
                            if_lt
                            root@debian:~# echo "$A" | sed 's/\(.....\)\( .*[^\.]\.\)\(.\).*/\2/'
                             r46.x, c0.
                            root@debian:~# echo "$A" | sed 's/\(.....\)\( .*[^\.]\.\)\(.\).*/\3/'
                            b


                            \(.....\)

                            trouve 5 caractères - donc if_lt

                            \( .*[^\.]\.\)
                            trouve un espace, ensuite avale tout
                            sous contrainte un caractère non point et cédé suit d'un point (donc 0.)

                            \(.\).*

                            cède un caractère suit de rien (.* réussie dans tous les cas)
                            le caractère cédé est b

                            si on écrivait
                            root@debian:~# echo "$A"
                            if_lt r46.x, c0.b
                            root@debian:~# echo "$A" | sed 's/\(.....\)\( .*[^\.]\.\)\(..\)\(.*\)/\1/'
                            if_lt
                            root@debian:~# echo "$A" | sed 's/\(.....\)\( .*[^\.]\.\)\(..\)\(.*\)/\2/'
                             r46.
                            root@debian:~# echo "$A" | sed 's/\(.....\)\( .*[^\.]\.\)\(..\)\(.*\)/\3/'
                            x,
                            root@debian:~# echo "$A" | sed 's/\(.....\)\( .*[^\.]\.\)\(..\)\(.*\)/\4/'
                             c0.b


                            \(.....\)
                            la mème chose
                            \( .*[^\.]\.\)
                            la même chose
                            \(..\)
                            cette fois je cherche un caractère suit d'un autre donc * est obligé de ceder 2 caractères qui son precédés par un point et dans notre cas, * va céder d'abord b ensuite . ensuite 0 ensuite c ensuite espace ensuite , ensuite x et * ne céde plus pusique il a trouvé un point avant le x
                            \(.*\)
                            avale tout
                            0
                            1. Modérateur
                              Ok vu comme ça, c'est plus clair mais ça (les regex) reste toujours plus ou moins obscur parfois ;-))

                              Merci beaucoup encore une fois.
                              0
                              1. Modérateur
                                mais ça (les regex) reste toujours plus ou moins obscur parfois ;-))

                                ça depends aussi de l'implementation dans les utilitaires
                                à savoir que le moteurs des regex ne font pas preuves d'inteligence mais de perseverence
                                une bonne habitude à prendre c'est de construire un regex en commençant avec le 1er jusqu'au dernier caractère, et pas de voir une regex dans son ensemble

                                c'est d'ailleurs ce que j'ai fait quand j'ai écrit ma version
                                je ne sais pas pourquoi mais j'ai l'impression que tu as écrit la regex en commençant avec le début mais tu la raisonnes en commençant avec la fin.

                                vieurou
                                pour le fait que ça ne marche pas avec ton fichier, c'est parce que on ne sait pas ce ton fichier contient, la structure, etc.
                                le test a été fait sur une banale variable, mais le contenu de ton fichier peut être bien plus complexe qu'une variable.
                                0
                                1. j'ai créé un fichier pour le test
                                  $ cat test.txt
                                  if_lt r19.x, c0.b
                                  
                                  $ sed -i -r -e '/^[ ]*#\|^$\|^\n*$/! {s/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/}' test.txt
                                  
                                  $ cat test.txt
                                  if_lt r19.x, c0.b
                                  


                                  autre truc bizarre :
                                  $ cat test.txt
                                  if_lt r19.x, c0.b
                                  
                                  $ sed -i -r -e '/^[ ]*#\|^$\|^\n*$/! {s/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/}' test.txt > retest.txt
                                  
                                  $ cat retest.txt
                                    (--ya rien--)
                                  


                                  du coup , je sais pas ...
                                  une idée???
                                  0
                                  1. Modérateur
                                    [tmpfs]$ cat plop
                                    if_lt r4.x, c0.b
                                    if_gt r15.w, c0.b
                                    
                                    [tmpfs]$ sed -i.bak  '/if_.. r\([0-9]\+\).*/{s/if_../\U&/;s/_/ /;s/\(.....\)\( .*[^\.]\.\)\(.\).*[a-z]$/\1.\3/}' plop
                                    
                                    [tmpfs]$ cat plop
                                    
                                    IF LT.x
                                    IF GT.w
                                    
                                    [tmpfs]$
                                    ;-))
                                    0
                                    1. Modérateur
                                      Regarde chez moi
                                      # cat vieurou
                                      if_lt r46.x, c0.b
                                      # sed -r -i.orig 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' vieurou
                                      # cat vieurou
                                      IF LT.x
                                      # cat vieurou.orig
                                      if_lt r46.x, c0.b
                                      # mv vieurou.orig vieurou
                                      root@debian:~# cat vieurou
                                      if_lt r46.x, c0.b
                                      # sed -r 's/if_(..).*[a-zA-Z][0-9]*\.([a-z]).*[a-z]$/IF \U\1\E.\2/' vieurou > vieurou_res
                                      # cat vieurou
                                      if_lt r46.x, c0.b
                                      # cat vieurou_res
                                      IF LT.x
                                      

                                      l'option -i permet la modification sur place
                                      avec la redirection j'écrit au lieu de stdout dans un fichier
                                      0
                                      • 1
                                      • 2