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

Résolu
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   -  
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   -
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

vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   2
 
$ 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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
mets ton fichier sur cjoint.com pour voir ce qui ne vas pas
tu peux le compresser avant de le mettre
1
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   2
 
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   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
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   2
 
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   2
 
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   2
 
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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
vieurou Messages postés 73 Date d'inscription   Statut Membre Dernière intervention   2
 
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
[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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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