Sustitution dans un fichier

Fermé
Lain - 22 févr. 2005 à 14:50
 Mlle Lain - 1 mars 2005 à 14:14
Bonjour,

Je cherche à faire quelque chose qui me parait tres simple mais, ah comme c'est marrant, je n'y arrive pas et je ne trouve pas de solutions en farfouillant à droite à gauche. Alors si quelqu'un avait la bonté de se pencher sur mon cas :/

Je fais un gros script shell qui lance plusieurs procedures d'installation. Le probleme vient d'une petite procedure.
Apres avoir reccuperer un certain nombre de nom de fichiers, je souhaite pour chacun d'entre eux remplacer un certain caractere par une chaine. Je pensais m'en sortir avec la commande awk mais je fais juste semblant de savoir m'en servir alors ca aide pas.
Extrait du script :
----------------------
#!/bin/sh
listeFichiers=$(find -name "*.lus" -type f -print | xargs grep -l @)
clear
for fichierCourant in $listeFichiers; do
awk -F /@/' { gsub ( $0 , "@", "petitpatapon" ) }' $fichierCourant
done
----------------------

Merci pour toute aide

Mademoiselle Lain
A voir également:

17 réponses

[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
22 févr. 2005 à 14:58
Salut Lain,

Si "vim" est installé sur ton système, tu peux l'utiliser en ligne de commande, comme çà :
vim -c "1,$ s/@/petitpatapon/g|wq" $fichierCourant

Il ne faut pas échapper le caractère "@", celà donne une erreur.


Dal
0
Merci Oh grand et Prompt Sauveur !

En esperant que vim sera installe partout où j'aurais à utiliser ce script :D
Ah au fait, echapper @ fait un peu tout plantouiller mais sans c'est parfait !!!
Merci encore !! :D

Mlle Lain
0
il y a aussi "sed" qui fait un peu la meme chose que "awk" il me semble, mais j'aurais du mal a t'en dire plus...

lain : tres bon anime en passant ;-)

Phiphi
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
22 févr. 2005 à 15:38
Re :)

Vim est installé très fréquemment par défaut sous Linux.

Phiphi a raison à propos de "sed"... avec sed, tu peux faire comme çà :
cat test.txt | sed 's/@/petitpatapon/g' > test.txt.temp
rm test.txt
mv test.txt.temp test.txt

Mais celà t'oblige à passer par la création d'un fichier intermédiaire temporaire.

Peut-être que awk permet de se passer de cette étape, mais je ne saurais l'affirmer avec certitude car je l'utilise assez peu.


Dal
0
Utilisateur anonyme
24 févr. 2005 à 17:51
saluche,

tu peux modifier directement le fichier avec -i
0
re moi
J'aime assez l'utilisation de vim et ca repond bien à ce que je veux
sauf bien sur pour un detail minime tout petit petit :
la chaine de remplacement n'est pas "petitpatapon" bien sur mais $repInstall
et ca le $repInstall il aime pas.
Comment y passer une variable ?

Lain
0

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

Posez votre question
re moi
J'aime assez l'utilisation de vim et ca repond bien à ce que je veux
sauf bien sur pour un detail minime tout petit petit :
la chaine de remplacement n'est pas "petitpatapon" bien sur mais $repInstall
et ca le $repInstall il aime pas.
Comment y passer une variable ?

Lain
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
22 févr. 2005 à 16:32
Re :)

chez moi :
#!/bin/sh

repInstall="petitpatapon"

vim -c "1,$ s/@/$repInstall/g|wq" test.txt

fontionne, à condition qu'il existe bien un "@" au moins dans le fichier (tu n'aurais pas essayé sur un fichier déjà traité ?).


Dal
0
Re
Merci de te pencher sur ce cas
en fait, je viens de comprendre : ma variable $repInstall passe pas parce qu'elle contient des "/"
faut donc que je neutralise ces bestiaux ... Mmm j'adore manipuler les chaines :D
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
22 févr. 2005 à 17:01
Dans ce cas, essaye quelque chose comme çà:
#!/bin/sh

repInstall="petit/pata/pon"
backslash='\\'
repInstall=`echo $repInstall | sed "s/\//$backslash\//g"`
vim -c "1,$ s/@/$repInstall/g|wq!" test.txt

Je ne suis pas sûr que ce soit la solution la plus simple, mais çà devrait marcher :)


Dal
0
Arf, on sent les pros :D Merveilleux !!
J'en etais encore à faire un "man tr" :D
Merci du coup de main.
Promis ca a fait avence la Science ;D

Lain
0
asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426
22 févr. 2005 à 23:49
Bonsoir :)

Ben j'ai peut-etre pas bien saisi ce qui doit rentrer et sortir de ça,
Mais tout betement, si tu as une liste de fichier dans une variable, et une directory dans une autre( $a=@fichier, $b=/dir/to/install/ )
Pourquoi ne pas tout simplement supprimer l'@ (tr -d @) et ensuite concatener les deux variable quand tu en as besoin ? ($a$b)

Si c'est bien ce que tu cherche a avoir, pas besoin de te torturer avec awk,sed,Vim et compagnie! (awk et sed sont incontournables ceci dit)
Quand a l'utilisation de Vim en batch, c'est une facilitée de l'editeur, mais c'est vraiment loin d'etre une excellente idée d'utiliser ça dans des script... :)
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
23 févr. 2005 à 11:18
Salut asevere,

Il me semblait que "tr" travaillait seulement au niveau des caractères.

Ma compréhension du problème de Lain est qu'elle souhaite substituer un caractère par une chaine de caractères dans un fichier (et si possible sans création d'un fichier temporaire d'après ses réponses), la particularité de cette chaîne étant qu'elle comporte des slashs. Peux tu nous préciser ta syntaxe "tr" ?

Quand a l'utilisation de Vim en batch, c'est une facilitée de l'editeur, mais c'est vraiment loin d'etre une excellente idée d'utiliser ça dans des script... :)

Je pense que ton jugement de valeur est basé sur le fait que Vim n'est pas une commande Unix POSIX.

Vim est un outil GNU qui est disponible sur tous les Unix libres, qu'il s'agisse de Linux ou de BSD et qui offre la puissance de cet éditeur de texte à la portée de la ligne de commande. C'est dommage de se priver de l'utiliser si on sait qu'on en dispose, sous prétexte que ce n'est pas une commande POSIX.

Pour une utilisation d'outils POSIX, Lain pourra aussi se référer à l'utilisation sed décrite en <4> de ce thread. Elle suppose la création d'un fichier temporaire, ce que l'utilisation de "vim" permet d'éviter (il se charge en fait de le faire, en prenant soin de ne pas écraser des fichiers existants lors de cette création).

Ceci dit, je suis intéressé par ta solution (ou d'autres) si elle permet au moins d'éviter d'avoir à échapper les slashs (ce qui est nécessaire avec "sed").


Dal
0
asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426
23 févr. 2005 à 22:35
Bsoir,

Le tr me sert simplement a supprimer l'arobase ('tr -d @') qui est inutil (sauf a trouver les fichiers qui doivent etre traités)

mettons que j'ai une liste @fic1 @fic2 @fic3, etc.
que je veux copier dans un repertoire cible.
[test]$ cat script
#!/bin/sh

touch @fic1 @fic2 @fic3

dir=cible/

if [ ! -d $dir ]; then
        mkdir $dir
fi;

var=$(find . -type f |grep @ )

for i in $var; do
        cp $i $dir$(echo $i |tr -d @)
done;
ça fonctionne sous le même principe si les fichiers sont du type cible/@fic* et a deplacer dans cible/sous_rep/fic*
#!/bin/sh

dir=sous_rep/

var=$(find . -type f |grep @ )

for i in $var; do
  base=$(echo $i | cut -f1 -d@ )
  fic=$(echo $i | cut -f2 -d@ )
  if [ ! -d $base$dir ]; then
    mkdir $base$dir
  fi;
  mv $i $base$dir$fic
done;


Bref, sauf a ne pas avoir saisi du tout ce qu'il fallait faire, je ne vois pas l'utilité de passer par sed, awk, ou autre ici, pourquoi se compliquer la tâche ?

Pour ce qui est de mon refus a utiliser Vim dans un script, en dehors du fait qu'il y ait une trés faible chance que vim ne soit pas présent, il y a la possibilité que tout rate a cause d'un vimrc mal combiné, le fait de devoir passer par des fichiers (vim n'est pas capable de lire la sortie standar) etc.
0
asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426
23 févr. 2005 à 22:49
Et juste pour le
Pour une utilisation d'outils POSIX, Lain pourra aussi se référer à l'utilisation sed décrite en <4> de ce thread. Elle suppose la création d'un fichier temporaire, ce que l'utilisation de "vim" permet d'éviter (il se charge en fait de le faire, en prenant soin de ne pas écraser des fichiers existants lors de cette création).

Sans ecraser le fichier:
sed -i 's/@/petitpatapon/' fichier
Et ça, sans bloquer le fichier pour ecriture!
Prenons le cas extreme, un fichier trés lourd, deux bacth Vim aussi lourds lancés dessus en même temps :(
Alors que deux sed :)

Sans utiliser de fichier:
#!/bin/sh
var=$(find . -type f |grep @ )
for i in $var; do
  res=$(echo $i | sed -e 's/@/petitpatapon/')
echo $res
done;

0
Utilisateur anonyme > asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022
24 févr. 2005 à 17:54
zut, j'aurais dû tout lire...
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 897 > Utilisateur anonyme
24 févr. 2005 à 17:58
J'allions te le dire justement !!!
Have a lot of fun ;-))
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
24 févr. 2005 à 11:55
Salut asevere,

1.

Il semble bien que "tr" ne soit pas utilisable pour ce que veux faire Lain, celui-ci n'opérant que des substitutions ou suppressions de caractères. Notre amie ne veux pas supprimer les "@" présents dans les fichiers, elle veux les remplacer par une chaîne de caractères... si tu les supprimes d'abord, je ne comprend pas comment tu sauras, après, où mettre la chaîne de remplacement dans le fichier.

Retournons à ce bon vieux sed, qui apparemment a pris une deuxième jeunesse :). Je ne connaissais pas l'option "-i", il semble que ce soit une option nouvelle intégrée dans une version améliorée de "sed" (sur FreeBSD c'est le package dans les ports "sed_inplace-2002.10.19 - A modified version of the sed(1) which can do in-place editing of files"), mais qui semble largement diffusée.

Après avoir vérifié que j'avais cette version, chez moi, la syntaxe :
sed -i 's/@/petitpatapon/' test.txt
donne : "sed: 1: "test.txt": undefined label 'est.txt'"

par contre :
sed -i "" 's/@/petitpatapon/' test.txt
fonctionne bien
on peut d'ailleurs faire :
sed -i "" 's/@/petitpatapon/g' test.txt
dans le cas où il y a plusieurs "@" à remplacer sur une ligne

Cette commande remplace le caractère "@" par la chaîne "petitpatapon", sans création d'un fichier temporaire (en revanche en mettrant ".bak" dans les guillemets à la place de "", on garde une copie de l'ancienne version).

On n'arrête pas le progrès ! Merci pour cette astuce asevere, que je vais garder dans mes tablettes !

2.

Tu as entièrement raison sur le fait que "sed" soit moins lourd que "vim" (quoique ce n'est pas emacs quand même), et compte tenu de cette option "-i", il semble effectivement préférable d'utiliser "sed" que "vim" (bien que la page de manuel déconseille d'utiliser l'option "-i" avec une extension vide).

Pour le fait que vim ne gère pas l'entrée standard, en fait celà devrait être possible. "vim -" permet de lui injecter l'entrée standard.

Mais celà ne présente pas d'intérêt pour Lain, qui veut travailler sur des fichiers existants, si j'ai bien compris.

Pour "vimrc" tu as raison, on n'est jamais à l'abri d'un utilisateur qui aurait saccagé son fichier de configuration. Il faut quand même relativiser, car "vim" fonctionne "out of the box" à l'installation (sans avoir à faire quoi que ce soit dans le fichier de configuration vimrc).

3.

Pour que Lain utilise "sed" dans son cas, il faudra quand même échapper les slashs.
#!/bin/sh

repInstall="/petit/pata/pon"
backslash='\\'
repInstall=`echo $repInstall | sed "s/\//$backslash\//g"`
sed -i "" 's/@/$repInstall/g' test.txt

Devrait fonctionner plus rapidement que vim et avec moins de ressources et çà me parait effectivement un bien meilleur choix pour des machines équipées de distributions récentes.

Si Lain risque de tomber sur des versions de "sed" ne supportant pas l'option "-i", alors, je pense que la proposition <4> est plus sûre de marcher à tout coup si elle tient à utiliser "sed".

Sinon.. "vim", l'option "-c" étant présente sur "vim" depuis longtemps :P


Dal
0
Utilisateur anonyme
24 févr. 2005 à 17:56
en fait avec sed tu n'es pas obligé d'utiliser le slash dans ton expression pour séparer les éléments

par exemple si ton expression contient des slash à ajouter ouy remplacer tu peux avoir une commande comme

sed -i "s#gros/patapouf#gropa/tapouf#g" machin.txt
0
Utilisateur anonyme > Utilisateur anonyme
24 févr. 2005 à 18:02
enfin, dans l'expression de substitution, je précise

pour la simple recherche d'un motif je crois pas

par exemple pour faire la substitution sur les lignes contenant prout je ne crois pas qu'on s'en tire avec
sed -i "#prout#s#gros/patapouf#gropa/tapouf#g" machin.txt
mais il faudra plutot
sed -i "/prout/s#gros/patapouf#gropa/tapouf#g" machin.txt
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
24 févr. 2005 à 18:16
Effectivement pour la substitution
repInstall="/petit/pata/pon"
sed -i "" "s#@#$repInstall#g" test.txt

Marche parfaitement. Merci Hector :)


Dal
0
asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426
24 févr. 2005 à 20:23
Pas le temps de tout reprendre, mais Lain travail sur des noms de fichiers et non sur des fichiers.
Si tu copie colle les deux exemples donnés en 13, tu verras que cela fonctionne, et que tu n'a pas forcement besoin d'avoir le @ pour le remplacer par la bonne chaine.

Et pour la config de vim, même si ça fonctionne sans rien, un utilisateurs qui en fait usage tout les jours peut avoir un vimrc conséquant, et sans vouloir mal faire, mettre des options qui empecherons ton script a toi de fonctionner...

++
0
Utilisateur anonyme
24 févr. 2005 à 22:44
arf oui je suis vraiment à l'ouest moi :(
0
asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426 > Utilisateur anonyme
24 févr. 2005 à 22:53
Hein !? :-S
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
25 févr. 2005 à 11:44
Salut asevere,

Bon, je comprends mieux le malentendu.

Lain disait dans son message d'origine :

(...)Apres avoir reccuperer un certain nombre de nom de fichiers, je souhaite pour chacun d'entre eux remplacer un certain caractere par une chaine.(...)

Cette phrase peut paraître équivoque, car elle peut signifier que "chacun d'entre eux" se rapporte au "nom de fichiers" ou aux "fichiers". J'ai penché pour la 2ème possibilité car Lain utilisait le pluriel "eux", et que cette interprétation est renforcée par cette ligne de son script :

listeFichiers=$(find -name "*.lus" -type f -print | xargs grep -l @)

Dans sa variable "$listeFichiers" il y a des noms de fichiers dont l'extension est ".lus" et qui comportent *dans le fichier* le caractère "@" (le passage du nom de chaque fichier dans grep est réalisé par "xargs", grep scanne donc chaque fichier et non pas simplement le résultat de la commande "find").

D'ailleurs, vu <1> et <2>, je crois qu'il n'y a pas de doutes là dessus, mais c'est à Lain de le confirmer, bien sûr.

Je ne conteste pas que tes scripts en <13> fonctionnent pour toi, mais il me semble, imho, qu'ils n'aident pas à résoudre le problème posé.


Dal
0
asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426
25 févr. 2005 à 12:16
Ha d'accord...
Autant pour moi alors :)

Je ne me suis basé que sur:
Apres avoir reccuperer un certain nombre de nom de fichiers, je souhaite pour chacun d'entre eux remplacer un certain caractere par une chaine.
Qui me semblait etre le probleme de Lain...

Désolé donc,
Mais ceci prouve bien le fait qu'il faut etre précis dans une demande,
Ne pas simpmlement coller deux lignes faisant parties d'un script, mais plutot faire un petit script comportant ces deux lignes, avec avant ça ce qu'iol faut pour construire un "jeu d'essai"...
0
[Dal] Messages postés 6193 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 4 juillet 2024 1 089
25 févr. 2005 à 12:53
Re :)

Pas de pb. çà m'a permis de réviser "tr", et de me mettre à jour sur sed, grâce à toi et à Hector. Il est sorti de bonnes choses de ce thread, j'espère qu'il sera utile à Lain et à d'autres.


Dal
0
Bijour,

Ouah !! je pensais pas que ma question souleverait autant de debats. Quel dommage que je n'ai pas eu la possibilite de les suivre.
Merci à tous en tout cas.
Toutes vos réponses me seront profitables.

Lain
0