Substitution par 'sed' une seule fois dans un fichier...

Le
David BERCOT
--Sig_/LGLe2=yhuG89jlCefAHAjZB
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Bonjour,

J'ai un petit problème avec 'sed'. Je souhaite effectuer le
remplacement d'une expression par une autre, mais uniquement une seule
fois dans un fichier.
Or, si je fais 'sed s/expr1/expr2/ monfichier', si expr1 est présent
plusieurs fois, elle sera remplacée à chaque fois.
Les recherches que j'ai effectuées ne parlent que du nombre de
substitutions (1, toutes, la dernière, etc) sur une ligne, et pas
sur un fichier

Auriez-vous une piste ?

Merci d'avance.

David.

--Sig_/LGLe2=yhuG89jlCefAHAjZB
Content-Type: application/pgp-signature; name=signature.asc
Content-Disposition: attachment; filename=signature.asc

--BEGIN PGP SIGNATURE--
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFHwZbjvSnthbGI8ygRAgvDAJ92S5J4TQubnc5q671SOWkyhJ6DIwCfQsvg
w2FK8L8z/hvEung+1kyX714=
=xZ5G
--END PGP SIGNATURE--

--Sig_/LGLe2=yhuG89jlCefAHAjZB--


--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to debian-user-french-REQUEST@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Sylvain Sauvage
Le #9710111
David BERCOT, dimanche 24 février 2008, 17:10:05 CET

Bonjour,



’jour,

J'ai un petit problème avec 'sed'. Je souhaite effectuer le
remplacement d'une expression par une autre, mais uniquement
une seule fois dans un fichier.
Or, si je fais 'sed s/expr1/expr2/ monfichier', si expr1 est
présent plusieurs fois, elle sera remplacée à chaque fois.
Les recherches que j'ai effectuées ne parlent que du nombre de
substitutions (1, toutes, la dernière, etc...) sur une ligne,
et pas sur un fichier...

Auriez-vous une piste ?



Il faut gérer le test et la boucle de lecture.
Je pense qu’un truc comme ça ferait l’affaire :

sed -e ':x;n;s/a/b/;Tx;:y;n;by'

ou, en plus clair :

# essayer la substitution
:x # étiquette 'x'
n # lire une ligne
s/a/b/ # faire la substitution
Tx # si la substitution a échoué, repartir en 'x'

# la substitution a réussi une fois
:y # étiquette 'y'
n # lire une ligne
by # repartir en y

Sed applique les instructions sur chaque ligne, donc, pour
éviter que le s/// soit appliqué à chaque ligne, il faut man ger
soi-même les lignes avant la substitution (boucle avec :x) et
après (boucle avec :y).

M’enfin, bon, il y a sûrement d’autres solutions⠀¦

--
Sylvain Sauvage
Sylvain Sauvage
Le #9710101
Sylvain Sauvage, dimanche 24 février 2008, 18:37:49 CET
[…]
M’enfin, bon, il y a sûrement d’autres solutions …



Ben oui, il y a plus simple : 0,/xxx/s//yyy/

0,/xxx/ : la commande ne s’applique que de la 1re ligne à celle qui
correspond à /xxx/
s//yyy/ : remplacer la correspondance par yyy.

--
Sylvain Sauvage
Jacques L'helgoualc'h
Le #9710091
David BERCOT a écrit, dimanche 24 février 2008, à 17:10 :
Bonjour,



bonsoir,

J'ai un petit problème avec 'sed'. Je souhaite effectuer le
remplacement d'une expression par une autre, mais uniquement une seule
fois dans un fichier.
Or, si je fais 'sed s/expr1/expr2/ monfichier', si expr1 est présent
plusieurs fois, elle sera remplacée à chaque fois.
Les recherches que j'ai effectuées ne parlent que du nombre de
substitutions (1, toutes, la dernière, etc...) sur une ligne, et pas
sur un fichier...

Auriez-vous une piste ?



~ $ echo 'toto
]titi
]toto
]tata' > fic


~ $ sed -e '/toto/{s//Glop/;:A;N;bA}' <fic
Glop
titi
toto
tata

Variantes :

sed -e ':A;N;$!bA;s/toto/Glop/' <fic
sed -ne 'H;${g;s/^n//;s/toto/Glop/;p}' <fic

Merci d'avance.



Hop zat elpse
--
Jacques L'helgoualc'h


--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
David BERCOT
Le #9710071
--Sig_/Bk+D1fK4qBvLUVSpMV7J.=A
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Le Sun, 24 Feb 2008 18:54:21 +0100,
Sylvain Sauvage
Sylvain Sauvage, dimanche 24 février 2008, 18:37:49 CET
>[…]
> M’enfin, bon, il y a sûrement d’autres solutions …

Ben oui, il y a plus simple : 0,/xxx/s//yyy/

0,/xxx/ : la commande ne s’applique que de la 1re ligne à   celle qui
correspond à /xxx/
s//yyy/ : remplacer la correspondance par yyy.



C'est nickel !!! Exactement ce que je cherchais !!!

Merci beaucoup.

David.

--Sig_/Bk+D1fK4qBvLUVSpMV7J.=A
Content-Type: application/pgp-signature; name=signature.asc
Content-Disposition: attachment; filename=signature.asc

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFHwb/uvSnthbGI8ygRAi8bAJwNvNllZvua0Cr3PW/oJ56qYrG7ngCgtSKZ
pOvpL5FTQ+NSw23VJSlsPXE =1/Yl
-----END PGP SIGNATURE-----

--Sig_/Bk+D1fK4qBvLUVSpMV7J.=A--


--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
fra-duf-no-spam
Le #9710011
Le 13933ième jour après Epoch,
Sylvain Sauvage écrivait:

Sylvain Sauvage, dimanche 24 février 2008, 18:37:49 CET
[…]
M’enfin, bon, il y a sûrement d’autres solutions …



Ben oui, il y a plus simple : 0,/xxx/s//yyy/

0,/xxx/ : la commande ne s’applique que de la 1re ligne à   celle qui
correspond à /xxx/



Je crois qu'il vaut mieux traduire ça par: "entre la ligne 1 et la
première contenant xxx", non?

s//yyy/ : remplacer la correspondance par yyy.



Par contre, je ne vois pas dans la doc que s//yyy/ remplace la
"correspondance", mais je te crois sur parole (enfin, je ferais un
test si nécessaire).
Jacques L'helgoualc'h
Le #9710001
François TOURDE a écrit, dimanche 24 février 2008, à 23:32 :
Le 13933ième jour après Epoch,
Sylvain Sauvage écrivait:

> Sylvain Sauvage, dimanche 24 février 2008, 18:37:49 CET
>>[???]
>> M???enfin, bon, il y a sûrement d???autres solutions???
>
> Ben oui, il y a plus simple : 0,/xxx/s//yyy/
>
> 0,/xxx/ : la commande ne s???applique que de la 1re ligne à celle qui
> correspond à /xxx/

Je crois qu'il vaut mieux traduire ça par: "entre la ligne 1 et la
première contenant xxx", non?



Non, c'est bien de la ligne 1 à la ligne de la /regexp/, incluses (c'est
peut-être la même) ; le truc de la ligne 0 est une extension GNU.

> s//yyy/ : remplacer la correspondance par yyy.

Par contre, je ne vois pas dans la doc que s//yyy/ remplace la
"correspondance", mais je te crois sur parole (enfin, je ferais un
test si nécessaire).



info sed, -> Addresses

The empty regular expression `//' repeats the last regular
expression match (the same holds if the empty regular expression is
passed to the `s' command). Note that modifiers to regular
expressions are evaluated when the regular expression is compiled,
thus it is invalid to specify them together with the empty regular
expression.
[...]
GNU `sed' also supports some special two-address forms; all these
are GNU extensions:
`0,/REGEXP/'
A line number of `0' can be used in an address specification like
`0,/REGEXP/' so that `sed' will try to match REGEXP in the first
input line too. In other words, `0,/REGEXP/' is similar to
`1,/REGEXP/', except that if ADDR2 matches the very first line of
input the `0,/REGEXP/' form will consider it to end the range,
whereas the `1,/REGEXP/' form will match the beginning of its
range and hence make the range span up to the _second_ occurrence
of the regular expression.

Note that this is the only place where the `0' address makes
sense; there is no 0-th line and commands which are given the `0'
address in any other way will give an error.

--
Jacques L'helgoualc'h


--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.net/?DebianFrench
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
fra-duf-no-spam
Le #9709991
Le 13933ième jour après Epoch,
Jacques L'helgoualc'h écrivait:

François TOURDE a écrit, dimanche 24 février 2008, à 23:32 :
Le 13933ième jour après Epoch,
Sylvain Sauvage écrivait:

> Sylvain Sauvage, dimanche 24 février 2008, 18:37:49 CET
>>[???]
>> M???enfin, bon, il y a sûrement d???autres solutions???
>
> Ben oui, il y a plus simple : 0,/xxx/s//yyy/
>
> 0,/xxx/ : la commande ne s???applique que de la 1re ligne à celle qui
> correspond à /xxx/

Je crois qu'il vaut mieux traduire ça par: "entre la ligne 1 et la
première contenant xxx", non?



Non, c'est bien de la ligne 1 à la ligne de la /regexp/, incluses (c 'est
peut-être la même) ; le truc de la ligne 0 est une extension GN U.



En relisant, je me suis rendu compte que ce que j'avais lu la première
fois de son explication n'avait rien à voir. J'avais lu: "La commande
ne s'applique qu'à la première ligne contenant xxx"... Bref, j' étais
dans le gaz encore :) Ou alors c'est le Médoc...

The empty regular expression `//' repeats the last regular
expression match (the same holds if the empty regular expression is
passed to the `s' command). Note that modifiers to regular
expressions are evaluated when the regular expression is compiled,
thus it is invalid to specify them together with the empty regular
expression.
[...]
GNU `sed' also supports some special two-address forms; all these
are GNU extensions:
`0,/REGEXP/'
A line number of `0' can be used in an address specification like
`0,/REGEXP/' so that `sed' will try to match REGEXP in the first
input line too. In other words, `0,/REGEXP/' is similar to
`1,/REGEXP/', except that if ADDR2 matches the very first line of
input the `0,/REGEXP/' form will consider it to end the range,
whereas the `1,/REGEXP/' form will match the beginning of its
range and hence make the range span up to the _second_ occurrence
of the regular expression.

Note that this is the only place where the `0' address makes
sense; there is no 0-th line and commands which are given the `0'
address in any other way will give an error.



Merci pour ces explications détaillées. Mais ne doit-on pas consi dérer
que 1,/xxx/ qui matche la seconde occurence n'est pas plutôt un bug?
Dans ce cas, que devrait faire /xxx/,/xxx/ ?

D'autre part, je viens de faire le test sur ma machine, que addr1 soit
0 ou 1, le match marche sur la première ligne.

Ok, je sais, je coupe les cheveux en sqrt(2), mais bon...
Sylvain Sauvage
Le #9709981
François TOURDE, lundi 25 février 2008, 00:09:57 CET
[…]
Merci pour ces explications détaillées. Mais ne doit-on pas
considérer que 1,/xxx/ qui matche la seconde occurence n'est
pas plutôt un bug?



Non, A1,A2 correspond à « de la ligne A1 à la ligne A 2 ».
Si une ligne est en correspondance avec A1, elle est prise.
Ensuite seulement, sed cherche la ligne qui correspond à A2,
après A1, et qui peut être la dernière ligne si aucune ne
correspond.
Sed ne peut pas aller en avant pour vérifier que A2 a une
correspondance, donc dès que A1 correspond à une ligne, le bloc
est commencé.

Une adresse correspond toujours à une ligne complète.

Tout ça fait que A1,A2 correspond toujours à au moins deux
lignes (sauf si A1 est la dernière ligne, évidemment).

Le 0 est une extension GNU pour le cas précis de la première
ligne. Ça fait toujours aux moins deux lignes : la 0 (qui
n’existe pas et qui serait avant la première (la 1)) et celle
qui correspond à la seconde adresse.

Dans ce cas, que devrait faire /xxx/,/xxx/ ?



Prendre toutes les lignes entre le premier xxx et le second
(s’il existe, sinon jusqu’à la fin).

D'autre part, je viens de faire le test sur ma machine, que
addr1 soit 0 ou 1, le match marche sur la première ligne.



Mauvais test, changer test :

$ cat >t
abc
abc
abc
abc
$ sed '0,/a/s/b/ /' t
a c
abc
abc
abc
$ sed '1,/a/s/b/ /' t
a c
a c
abc
abc

Avec 1, A2 ne peut commencer qu’à la deuxième ligne, do nc le
bloc correspond aux deux premières lignes et s/b/ / est appliqué
à chacune des lignes du bloc, donc deux fois.

Ok, je sais, je coupe les cheveux en sqrt(2), mais bon...



Biiip, irrationnel détecté !

C’est pas déconseillé, l’alcool et les Méd ocs ?

--
Sylvain Sauvage
Publicité
Poster une réponse
Anonyme