Sed et ses caprices (ou les miens)

Résolu/Fermé
bkrqpzef Messages postés 197 Date d'inscription samedi 19 novembre 2005 Statut Membre Dernière intervention 13 juillet 2011 - 18 mars 2009 à 11:17
bkrqpzef Messages postés 197 Date d'inscription samedi 19 novembre 2005 Statut Membre Dernière intervention 13 juillet 2011 - 18 mars 2009 à 19:19
Salut,
il faudrait que je transforme le mot "BATEAU" par un autre mot, par exemple "MAISON". Le mot est contenu dans un fichier du repertoire courant, mais j'ignore lequel, je pensais utiliser :
$sed -i 's/BATEAU/MAISON/' *.*

Malheureusement, il y a plusieurs fichiers qui contiennent le mot BATEAU. Avec cette commande, je les modifie tous. Or je voudrais qu'il s'arrête une fois qu'il en a trouvé un.
Est-il possible de limiter sed à une seule modification ? Si oui comment svp ?

Exemple :
$cat bob1.txt
BATEAU
$cat bob2.txt
BATEAU


$sed -i 's/BATEAU/MAISON/' *.*


$cat bob1.txt
MAISON
$cat bob2.txt
MAISON


Or, je recherche à avoir ce type de résultat :

$cat bob1.txt
MAISON
$cat bob2.txt
BATEAU


Sachant que je ne connais pas dans quel fichier est le mot BATEAU que je veux modifier.

8 réponses

jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
18 mars 2009 à 11:30
Salut,

Avec l'option "-s" de sed et la commande "q" (quitter) c'est possible. Extrait de la FAQ sur SED :
-s, --separate

    * Si plusieurs fichiers sont fournis en entrée, les traiter un à un plutôt que 
      comme une seule et même page


:
[rep]$ grep -H 'BATEAU' fich*
fich1.txt:BATEAU
fich2.txt:BATEAU
fich3.txt:BATEAU
fich4.txt:BATEAU
fich5.txt:BATEAU

[rep]$ sed -s -i 's/BATEAU/MAISON/;q' fich*

[rep]$ grep -EH '(BATEAU|MAISON)' fich*
fich1.txt:MAISON
fich2.txt:BATEAU
fich3.txt:BATEAU
fich4.txt:BATEAU
fich5.txt:BATEAU

[rep]$ 
;-))
1
bkrqpzef Messages postés 197 Date d'inscription samedi 19 novembre 2005 Statut Membre Dernière intervention 13 juillet 2011 5
18 mars 2009 à 15:03
Super !
Oui changer les séparateurs !!!! C'est une habitude que je dois prendre :p
Merci pour la leçon, tout fonctionne.
1
En réalité, le tiens pouvais également fonctionner, si tu n'avais pas distraitement glisser un "/" de trop tout à la fin après ton "}"

Ta syntaxe était certe un peu bordélique mais fonctionnait également, la preuve:

echo GOOGLE | sed '/GOOGLE/ {s//<a href="http:\/\/www\.google\.fr\/google\/index\.html">Google<\/a>/;q}'
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895 > m4ni4k
18 mars 2009 à 16:31
;-))
0
Un conseil, commence par lire les messages d'erreur, ils sont parfois particulièrement instructifs

sed: -e expression n°1, caractère 85: caractères inutiles après la commande

te mettait clairement le nez dans ta merdouille
;)
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
18 mars 2009 à 11:58
En y réfléchissant bien, l'option "-s" n'est pas nécessaire, et cette syntaxe serait plus appropriée :
sed -i '/BATEAU/ {s//MAISON/;q}' fich*
;-))
0
bkrqpzef Messages postés 197 Date d'inscription samedi 19 novembre 2005 Statut Membre Dernière intervention 13 juillet 2011 5
18 mars 2009 à 13:03
Pffiiioou,
c'est exactement ce que je cherchais.
sed -i '/BATEAU/ {s//MAISON/;q}' fich*

Même si je ne comprend pas cette ligne. :p
Je vais l'étudier d'un peu plus près. Merci !!!
0

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

Posez votre question
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
18 mars 2009 à 13:20
Par défaut lorsqu'on donne plusieurs fichiers en entrée à sed, ils sont vus comme un seul et unique fichier (d'où ma confusion avec l'option "-s", je pensais le contraire). A partir de là, il suffit d'employer la commande "q" (quitter) qui comme son nom l'indique, quitte le script dès que la condition est trouvée, donc dès que la 1ère substitution a eu lieu...

En ce qui concerne la syntaxe : /BATEAU/ {s//MAISON/}

/BATEAU/
c'est le motif à rechercher

s//MAISON/
Pas la peine de répéter le motif vu que c'est celui-là même qu'on veut remplacer, donc on utilise la syntaxe s// qui correspond à s/BATEAU/

Le tout entre accolades pour grouper les commandes (s et q) et signifier qu'elles ne doivent être appliquées qu'au motif fourni...
0
bkrqpzef Messages postés 197 Date d'inscription samedi 19 novembre 2005 Statut Membre Dernière intervention 13 juillet 2011 5
18 mars 2009 à 13:37
Humm,
sed -i '/GOOGLE/ {s//<a href="http:\/\/www\.google\.fr\/google\/index\.html">Google<\/a>/;q}/' *

me sort :
sed: -e expression n°1, caractère 85: caractères inutiles après la commande

Une idée ? :p
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 895
18 mars 2009 à 13:56
Change les séparateurs de la commande "s" (/ par défaut) par des pipes (|) ou tout autre caractère ne se trouvant pas dans la chaîne de remplacement...
[rep]$ grep -H 'GOOGLE' fich*
fich1.txt:GOOGLE
fich2.txt:GOOGLE
fich3.txt:GOOGLE
fich4.txt:GOOGLE
fich5.txt:GOOGLE

[rep]$ sed -i '/GOOGLE/ {s||<a href="http://www.google.fr/google/index.html">Google</a>|;q}' fich*

[rep]$ grep -EHi 'google' fich*
fich1.txt:<a href="http://www.google.fr/google/index.html">Google</a>
fich2.txt:GOOGLE
fich3.txt:GOOGLE
fich4.txt:GOOGLE
fich5.txt:GOOGLE
[rep]$  
0
bkrqpzef Messages postés 197 Date d'inscription samedi 19 novembre 2005 Statut Membre Dernière intervention 13 juillet 2011 5
18 mars 2009 à 19:19
Ouaik :D
Mais jipicy a accidentellement résolu un autre de mes problème avec ses conseils.
J'utilise un appel system() en langage c pour la commande sed :
Ce qu'il me fait un truc de fou du genre
system("sed -i 's/\\//\\\\\\//g' *");

Pour remplacer / par \ et /. :D
J'ai pu du coup rendre mon code un peu plus lisible.
Merchi à vous !
0