Replacer texte sur la première occurrence du fichier
RésoluBonjour,
Je cherche a écrire un script qui va modifier des informations sur des fichiers générés automatiquement. Mon fichier ressemble initialement à ça :
toto 1111
tata 1234
toto 1111
J'aimerais changer uniquement le 1er "toto 1111" en "toto 1269" avec la commande sed.
J'arrive a le changer les deux toto avec l'indice de substitution s mais même sans mettre le g pour l'appliquer à tout le fichier, il me modifie les deux.
Merci d'avance pour vos réponses.
- Replacer texte sur la première occurrence du fichier
- Fichier bin - Guide
- Comment réduire la taille d'un fichier - Guide
- Fichier epub - Guide
- Fichier rar - Guide
- Fichier .dat - Guide
5 réponses
hello
$ awk '/toto/ && !n++ {$2=1269} {print $0}' fichier toto 1269 tata 1234 toto 1111 $ sed '0,/toto/{s/1111/1269/}' fichier toto 1269 tata 1234 toto 1111 $
La commande marche mais le résultat est généré dans un autre fichier (outputfile.txt). Il faut de plus veiller à ce que la ligne soit exactement conforme (pas d'espace en plus). La commande cat -A permet de vérifier en affichant $ en fin de ligne.
Ensuite, la commande fournie par xHaMaz génère le résultat dans un autre fichier. Si tu tu veux que la substitution soit faite en place dans le fichier d'entrée (disons input.txt), il faut utiliser l'option -i.
(mando@silk) (~) $ cat -A input.txt
toto 1111$
tata 1234$
toto 1111$
(mando@silk) (~) $ sed -i '1s/^toto 1111$/toto 1269/' input.txt
(mando@silk) (~) $ cat -A input.txt
toto 1269$
tata 1234$
toto 1111$
Bonne chance
Merci, en effet ça fonctionne ! j'utilise la commande sed.
Pourrais-tu m'expliquer à quoi sert le 0 ?
Merci d'avance !
La solution #3 proposée par dubcek basée sur sed repose sur la notion de range specifier (voir ici). Expliquons cette notion sur ton exemple :
- Si tu connais le numéro de ligne (ici 1) sur lequel la modification doit opérer , tu peux écrire :
sed '1,1s/^toto 1111$/toto 1269/' input.txt
ou de manière plus laxiste :sed '1,1s/1111/1269/' input.txt
... ce qui signifie :- sur la plage de ligne allant de 1 à 1 incluses,
- applique la substitution qui remplace la première occurrence de 1111 par 1269).
- La commande de dubcek #3 est plus générale, car elle n'a pas d'a priori sur la ligne dans laquelle figure la première occurrence à substituer :
sed '0,/toto/{s/1111/1269/}' input.txt
... ce qui signifie :- cherche la première ligne qui est validée par l'expression rationnelle "toto" (donc la première ligne qui contient toto) : c'est une syntaxe spécifique, voir ici
- puis, applique la substitution qui remplace la première occurrence de 1111 par 1269
- si tu remplaces le 0 par un entier n strictement positif, la recherche de la ligne se fait pour toutes les lignes validées à partir de la ligne n incluse
Bonne chance
Et sais tu s'il est possible de remplacer le début de la recherche (0) dans l'exemple par une adresse ?
Je m'explique, à la place cette commande :
sed '0,/toto/{s/1111/1269/}' input.txt
j'aimerai modifier le 0 mais non pas par un entier mais par une phrase.
Par exemple :
toto 1111
tata 1234
toto 1111
titi 4321
tata 6789
toto 1111
j'aimerai modifier le dernier toto uniquement et a partir de tata 6789 par exemple. J'imaginai un truc comme ça :
sed 'tata 6789,/toto/{s/1111/1269/}' input.txt
Mais ça ne marche pas
Je ne sais pas si tu peux faire comme tu essayes de faire, mais c'est peut-être faisable.
Personnellement, je pense qu'il devient d'écrire un script shell, dans lequel tu lances une première commande trouve le numéro de ligne de la dernière occurrence de toto.
j=`grep -n "^toto" fichier.txt | tail -n 1 | cut -d":" -f 1` echo "$j"
... et une autre le numéro de ligne qui contient "tata 6789" :
i=`grep -n "^tata 6789$" fichier | head -n 1 | cut -d":" -f 1` echo "$i"
Il faut ensuite contrôler que i et j sont bien définis (donc que les deux motifs cherchés on été trouvés) et comparer i et j (i < j). Dans ce cas, un remplacement est possible, et $j te donne le numéro de ligne où opérer, tu peux utiliser sed et un range specifier basé sur $j.
if [[ -z "$i" && -z "$j" && "$i" -lt "$j" ]] then eval "sed '${j},${j}s/^toto/toto 5678/' fichier.txt" fi
Bon je ne te cache pas que moi je ferais tout ça en python plutôt qu'en shell mais ça c'est affaire de goût :-D
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question