Shell unix : Remplacement de valeurs à partir d'un fichier

Résolu/Fermé
agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015
- Modifié par agobats le 13/09/2015 à 17:45
dna.factory
Messages postés
22866
Date d'inscription
mercredi 18 avril 2007
Statut
Contributeur
Dernière intervention
11 août 2022
- 5 févr. 2016 à 11:13
Bonjour,

je voudrais, à partir d'unix, procéder à un remplacement de valeurs de texte à partir d'une table de correspondance.
Je m'explique : j'ai donc une table de correspondance appelée table.txt qui contient 2 colonnes, la première contient l'ancienne valeur et la deuxième la nouvelle valeur.
A partir de cette table je veux remplacer dans un fichier file.out les anciennes valeurs par les nouvelles.

table.txt :
orange pomme
banane kiwi
fraise framboise
peche abricot
...

file.out :
peche France
orange Maroc
peche Nouvelle-Zelande
fraise Espagne

Merci beaucoup de votre aide.

3 réponses

zipe31
Messages postés
36319
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 574
13 sept. 2015 à 23:30
$ cat table 
orange pomme
banane kiwi
fraise framboise
peche abricot

$ cat out
peche France
orange Maroc
peche Nouvelle-Zelande
fraise Espagne

$ join -1 1 -2 1 -o 1.2 2.2 <(sort table) <(sort out)
framboise Espagne
pomme Maroc
abricot France
abricot Nouvelle-Zelande

1
agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015

14 sept. 2015 à 00:47
Mon exemple n'était pas bon car le fichier final n'est pas forcément sur 2 colonnes. le texte à remplacer peut se retrouver 2 fois dans une même ligne à des emplacements différents.
De plus je ne dois surtout pas trier les données

Désolé de ne pas avoir été suffisamment précis dans mon exemple. J'aurai dû te joindre les fichiers mais comme je ne les avais pas avec moi.

Ceci dit la commande join pourra me servir pour une autre application.

Salutations.
0
agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015
> agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015

Modifié par agobats le 14/09/2015 à 20:28
Bonjour,

Cette-fois-ci je joins un extrait des fichiers. Après vérification, je me suis trompé sur la position du texte à remplacer. Le fichier a toujours ce format et la valeur a changer est toujours au même endroit (avant-denier caractère) et n'apparaît qu'une fois par ligne. Je ne trouve pas la solution, je pensais qu'avec une commande sed et éventuellement un cut ça serait possible, mais comme je suis un peu néophyte sur les boucles.
Fichier d'entrée :
K 1000. 1000.
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 2255. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 4460. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3200. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3040. 2925.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 3040. 2270.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 3040. 2630.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 3040. 2780.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3040. 1440.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3210. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 4460. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='1'

Table :
1 (A12)
2 (A13)
3 (A15)
4 (A16)
5 (A17)

Fichier résultat :

K 1000. 1000.
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 2255. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 4460. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3200. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3040. 2925.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2270.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2630.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2780.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3040. 1440.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3210. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 4460. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A12)'

Merci pour votre aide.
0
dubcek
Messages postés
18533
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
11 août 2022
5 554
Modifié par dubcek le 15/09/2015 à 09:04
hello
$ awk -F "[ ']" '/[(]/  {t[$1]=$2; next} /=/ {$5=t[$5] "'\''"; sub("= ", "='\''")} {print}' table fichier
K 1000. 1000.
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 2255. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 4460. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3200. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3040. 2925.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2270.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2630.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2780.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3040. 1440.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3210. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 4460. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A12)'
0
zipe31
Messages postés
36319
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 574 > dubcek
Messages postés
18533
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
11 août 2022

15 sept. 2015 à 09:53
Salut,

awk c'est quand même puissant ;-))

Bon je mets quand même ma solution (bash + sed) ;-))

$ cat table 
1 (A12)
2 (A13)
3 (A15)
4 (A16)
5 (A17)

$ cat fich
K 1000. 1000.
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 2255. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 4460. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3200. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3040. 2925.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 3040. 2270.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 3040. 2630.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 3040. 2780.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3040. 1440.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='3'
9 3210. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='5'
9 4460. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='1'

$ cat foo.sh
#!/bin/bash

while read line
do
sed -i "/^ATTRIBUT/{s/='${line% *}'/='${line#* }'/}" fich
done < table

$ ./foo.sh

$ cat fich
K 1000. 1000.
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 2880. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 2255. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 4460. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3200. 3040.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3040. 2925.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2270.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2630.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 3040. 2780.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3040. 1440.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A15)'
9 3210. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A17)'
9 4460. 1380.
ATTRIBUT CHANGE NAME=MATERIAL VALUE='(A12)'
0
agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015
> dubcek
Messages postés
18533
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
11 août 2022

15 sept. 2015 à 22:53
Bonsoir,
Merci pour votre réponse. vous êtes impressionnants tous les 2! La commande awk me plait bien même si je n'ai pas tout compris. Par contre je n'arrive pas à l'exécuter cause erreur de syntaxe.
J'ai le message suivant :
Syntax error near line 1
bailing out near line 1
Pour la commande sed, j'ai aussi le même problème avec un message d'erreur ( illegal ...)
Comme j'utilise une station sun avec unix solaris, je pense qu'il s'agit d'une différence de langage.
zut je viens de m'apercevoir que je n'avais pas précisé le système d'exploitation. Désolé.
Si vous aviez la commande équivalente en sh, ça m'aiderait bien.
A noter que la valeur à changer dans l'exemple peut être sur plusieurs caractères mais sera toujours entourée de cotes et précédée du même texte débutant par ATTRIBUT.

Salutations.
0
zipe31
Messages postés
36319
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 574
13 sept. 2015 à 19:41
Salut,

Pas sûr d'avoir tout pigé ;-(

Et le fichier final doit ressembler à ???
0
agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015

13 sept. 2015 à 23:08
Salut,
Le fichier final doit ressembler à cela :

abricot France
pomme Maroc
abricot Nouvelle-Zelande
framboise Espagne

Merci d'avoir jeté un oeil déjà. ;-(
0
dubcek
Messages postés
18533
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
11 août 2022
5 554
16 sept. 2015 à 08:18
sur Solaris, utiliser nawk à la place de awk
0
dubcek
Messages postés
18533
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
11 août 2022
5 554
Modifié par dubcek le 16/09/2015 à 10:31
ce code ne passe pas sur Solaris ?
sed "s+^+s/'+; s+ +'$/'+;s+)+)'/+"  table| sed -f - fichier

essayer
sed -e "s+^+s/'+" -e "s+ +'$/'+" -e "s+)+)'/+"  table| sed -f - fichier
0
agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015

16 sept. 2015 à 13:52
Bonjour,
Avec la commande nawk ça ne passe pas j'ai le message suivant :
nawk : syntax error at source line
context is '/[(]/ {t[$1]=$2; next} >>> /= <<<
nawk: bailing out at source line 1
Avec les commande sed, j'ai le message :
Cannont open pathern-file
Désolé pour le dérangement. Ne serait-il pas possible de passer par une commande plus simple du genre :
on déclare les 2 valeurs, puis dans une boucle on insére la commande suivante :
sed 's/$val1/$val2/g' <file.input >file.out

Salutations.
0
dubcek
Messages postés
18533
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
11 août 2022
5 554
Modifié par dubcek le 16/09/2015 à 14:38
essayer sed en 2 étapes
sed -e "s+^+s/'+" -e "s+ +'$/'+" -e "s+)+)'/+"  table > cmd.sed
sed -f cmd.sed fichier
et
$ cat code.awk
/[(]/ {t[$1]=$2; next}; /=/ {split($0, a, "'"); sub("'" "[0-9]+", "'" t[a[2]])}; {print}
$ nawk -f code.awk table fichier
0
agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015

Modifié par agobats le 16/09/2015 à 16:59
sur la cammande awk, j'ai le message suivant :
ksh: syntax error: '(' unexpected
Pour la commande sed c'est nettement mieux sauf que le fichier n'est pas mis à jour. J'ai aussi supprimé le $, car avec rien se se passait. Par contre je voudrais que le fichier soit sauvegardé et pas seulement affcihé.
Merci pour tout
0
zipe31
Messages postés
36319
Date d'inscription
dimanche 7 novembre 2010
Statut
Contributeur
Dernière intervention
27 janvier 2021
6 574 > agobats
Messages postés
17
Date d'inscription
dimanche 20 juillet 2014
Statut
Membre
Dernière intervention
17 septembre 2015

16 sept. 2015 à 16:38
Pour la commande sed c'est nettement mieux sauf que le fichier n'est pas mis à jour complétement.
Pas complètement n'est pas une réponse pouvant nous mettre sur la voie ;-(
Peux-tu développer s'il te plaît ?

J'ai supprimé le $, car avec rien se se passait
T'es sûr ? ;-\
Le caractère $ représente la fin de ligne et rien d'autre.

Par contre je voudrais que le fichier soit sauvegardé et pas seulement affcihé.
Suffit de faire une redirection
sed -f cmd.sed fichier > fich.final
0