IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

modification de fichier texte en shell


Sujet :

Linux

  1. #1
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut modification de fichier texte en shell
    Bonjour,

    Je débute sur les script shell et j'aimerai écraser mon fichier $fic après avoir remplacer les espaces qui le composent par des ;


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    for fic in *.txt                      #Pour tous les fichiers texte du dossier
    do
    for i in `cat *.txt`                 #Lecture du contenu
    	do
    	sed "s/  /;/g" *.txt > tmp    #remplacement (pas de problème), envoi vers un fichier nommé tmp
    	mv tmp $fic  #renommage par le nom de fichier initial (MARCHE PAS)
    	done
    done


    il me le renomme en tmp (en fait il me le renomme pas)

    y a un problème avec la variable de la première boucle ??


    Merci d'avance pour votre aide

  2. #2
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Citation Envoyé par jonathan1
    Bonjour,

    Je débute sur les script shell et j'aimerai écraser mon fichier $fic après avoir remplacer les espaces qui le composent par des ;
    .../...

    Solution (l'option -i de sed évite de passer par un fichier intermédiaire) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for file in *txt ; do
        sed -i "s/ /;/g" $file
    done
    Loi de Murphy:
    La Théorie c'est quand ça ne marche pas mais que l'on sait pourquoi.
    La Pratique c'est quand ça marche mais qu'on ne sait pas pourquoi.
    Quand la théorie rejoint la pratique ça ne marche pas et on ne sait pas pourquoi.

  3. #3
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Bonjour

    J'utilise shell sous windows et apparemment l'option -i n'est pas connue.

    Le problème, c'est qu'en fait, avec ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for fic in *.txt                      #Pour tous les fichiers texte du dossier
    do
    for i in `cat *.txt`                 #Lecture du contenu
    	do
    	sed "s/  /;/g" *.txt > $fic 
    	done
    done
    il me vide le fichier source.

  4. #4
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    nb=0
     
    for fic in *.txt
    do
    let "nb += 1"
     
    for i in $fic
    	do
    	sed "s/  /;/g" $fic> "fichier$nb.txt"
    	done
     
    done
    Je pourrai faire comme ca mais dans ma deuxième boucle, j'ai l'impression qu'il ne reprend pas la variable $fic

  5. #5
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    for i in *; do
         mv "$i" "`echo "$i" | tr \  _`"
    done  #renommage des fichiers car si il y a des espaces, il ne prend pas le nom des fichier entièrement
     
    for fic in *txt
    do
    let "nb += 1"
     
    for i in `cat "$fic"`
    	do
    	sed "s/  /;/g" $fic> "$nb$fic"
    	done
     
    done
    Voila, j'ai à peu prés obtenu le résultat escompté . J'aurai préféré ne pas avoir à renommer les fichiers (1ere boucle).
    Si quelqu'un à une explication pour ca...

    Merci

  6. #6
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Points : 28 119
    Points
    28 119
    Par défaut
    Bonjour,

    Si tu as accès à perl :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perl -pi -e 's/  /;/g' ton_fichier
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  7. #7
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Non pas de perl...

    Par contre, autre question :

    Comment utiliser sed pour qu'il ne prenne en compte que les chaines consécutives d'au moins deux caractères.

    j'ai essayémais il prend tous les caractères.

    RE autre question :

    quel code utiliser pour le retour chariot.


    MERCI

  8. #8
    Membre chevronné

    Profil pro
    Inscrit en
    Mars 2004
    Messages
    1 296
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 296
    Points : 1 803
    Points
    1 803
    Par défaut
    enfin il y a quand meme un probleme dans ton truc ......
    pour tout les fichiers d'un repertoire .... OK
    mais une boucle sur le contenue du fichier pour passer pas sed ... Aie Aie
    sed directement, sed traite un fichier complet et nom pas une ligne ....

    pour au moins 2 caracteres utilise .. (2points) puis l'etoile soit ..*
    Marc
    Slackware for ever ......
    BASH - KSH ( http://marcg.developpez.com/ksh/ )

  9. #9
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Merci,

    Effectivement ca fonctionne sans la boucle.
    Par contre pour au moins deux caractères (..*) c

  10. #10
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    désolé mauvaise frappe
    Merci,

    Effectivement ca fonctionne sans la boucle.
    Par contre pour au moins deux caractères (..*) ca ne fonctionne pas.

    Mais je vais être plus direct car là

    Je souhaite passer d'un fichier formatter comme ca (les tirets bas sont des espaces) :
    champ_________valeur
    champ1________valeur1
    ...
    à un fichier comme ca (correctement formatter)
    champ;champ1;...
    valeur;valeur1;...

    Il faut que je copie dans un fichier destination les caractères situés avant au moins deux espaces.(partie à gauche des espaces)
    Puis que je copie dans un autre fichier les caractères qui se situe après une chaines consécutive d'espace.(partie à droite)

    que je mette dans chaque fichier tous les caractères sur la même ligne (en séparant)

    que je regroupe les deux fichiers.

    ca doit être à peu prés ca. (comme ce n'est que mon deuxième shell je crois que ca va être dur)

    Si vous avez des conseils...

    Merci.

  11. #11
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Citation Envoyé par jonathan1
    désolé mauvaise frappe
    Merci,

    Je souhaite passer d'un fichier formatter comme ca (les tirets bas sont des espaces) :
    champ_________valeur
    champ1________valeur1
    ...
    à un fichier comme ca (correctement formatter)
    champ;champ1;...
    valeur;valeur1;...

    Il faut que je copie dans un fichier destination les caractères situés avant au moins deux espaces.(partie à gauche des espaces)
    Puis que je copie dans un autre fichier les caractères qui se situe après une chaines consécutive d'espace.(partie à droite)
    - que je mette dans chaque fichier tous les caractères sur la même ligne (en séparant)
    - que je regroupe les deux fichiers.

    Ça doit être OK

    Fichiers entrée n° 1 : tst1.txt
    champ1_____info1
    champ2___info2
    champ3_info3
    champ4__info4


    Fichiers entrée n° 2 : tst2.txt
    champ5__info5


    Fichier sortie "FicChamps" :
    champ1;champ2;champ3;champ4;champ5;
    info1;info2;info3;info4;info5;


    Script :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
     
    > ConcatFile.dat	#-- Initialisation fichier
     
    #
    ### Nota :  le caractère '*' signifie 0 à n fois le caractère précédent
    ###         aussi, /  */ est vrai si 2 espaces ou +              
    #
    for file in *.txt ; do
        sed "s/  */;/g" $file >> ConcatFile.dat
    done
    > FicChamps	#-- Initialisation fichier
    > FicInfos
    while read ligne ; do
    	VarChamp=`echo $ligne | cut -d";" -f1`
    	VarInfo=`echo $ligne | cut -d";" -f2`
    	echo -n $VarChamp";" >> FicChamps 
    	echo -n $VarInfo";" >> FicInfos
    done < ConcatFile.dat
     
    echo "" >> FicChamps 
    echo "" >> FicInfos
     
    cat FicInfos >> FicChamps
    cat FicChamps
    Loi de Murphy:
    La Théorie c'est quand ça ne marche pas mais que l'on sait pourquoi.
    La Pratique c'est quand ça marche mais qu'on ne sait pas pourquoi.
    Quand la théorie rejoint la pratique ça ne marche pas et on ne sait pas pourquoi.

  12. #12
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Bonjour,

    Merci pour cette réponse. J'pensais me repencher sur le problème, mais bon, tout le travail est fait...Encore merci BlaireauOne.

    Néanmoins je suis sous windows et je réaffirme que sur mon poste le
    sed "s/ */;/g" (pour au moins deux espaces ne passe pas, il prend tous les espaces.)

    Je devrai réussir à pallier le problème.


    MERCI

  13. #13
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Je reviens car je ne suis pas au bourt de mes peines...

    en ce qui concerne mon problème avec sed pour selectionner au moins deux caractères, il semble que sur mon poste je dois écrire "s/???*/?/g" (trois fois le caractère à remplacer avant * (allez comprendre).

    En utilisant awk, c'est plutôt efficace aussi.

    Par contre j'ai bo remplacer les retours chariot par un séparateur, mes fichiers restent en colonne.

    fichier source

    valeur1
    valeur2
    ...


    fichier destination (après avoir remplacé les retours chariot par ? (par exemple))

    ?valeur1
    ?valeur2
    ...

    Je ne suis pas beaucoup avancé...

    Il me faudrait

    valeur1?valeur2?...


    Pourriez vous m'aidez encore un peu

    MERCI d'avance

  14. #14
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Citation Envoyé par jonathan1
    Je reviens car je ne suis pas au bourt de mes peines...

    .../...
    Par contre j'ai bo remplacer les retours chariot par un séparateur, mes fichiers restent en colonne.
    .../...

    En shell bash, echo sans retour chariot --> option -n
    Ça ne semble pas marcher avec ton shell, alors essaie --> \c comme ci-dessous :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	echo $VarChamp";\c" >> FicChamps 
    	echo $VarInfo";\c" >> FicInfos
    Loi de Murphy:
    La Théorie c'est quand ça ne marche pas mais que l'on sait pourquoi.
    La Pratique c'est quand ça marche mais qu'on ne sait pas pourquoi.
    Quand la théorie rejoint la pratique ça ne marche pas et on ne sait pas pourquoi.

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 5
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par jonathan1
    Je reviens car je ne suis pas au bourt de mes peines...

    en ce qui concerne mon problème avec sed pour selectionner au moins deux caractères, il semble que sur mon poste je dois écrire "s/???*/?/g" (trois fois le caractère à remplacer avant * (allez comprendre).
    C'est parfaitement logique

    Comme le disait BlaireauOne, le caractère '*' signifie 0 à n fois le caractère précédent, aussi /..*/ est vrai si 1 caractère ou +, et donc /...*/ pour 2 caractères ou +, etc.
    Il faut comprendre ceci: d'abord on cherche 2 caractères (les 2 premiers points) puis on cherche un caractère répété entre 0 et n fois (le .*)
    Enfin, le "." remplace n'importe quel caractère, pour chercher un espace on met un espace à la place, pour chercher un t on met un "t" à la place.
    Pour plus d'info, http://fr.wikipedia.org/wiki/Expressions_rationnelles

  16. #16
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Bonjour,

    Merci pour vos réponses le ";\c" fonctionne nikel.

    J'aimerai que le résultat de mon script soit parfait, et pour cela, je dois avoir une approche un peu différente.
    Elle consiste à compter les caractères jusqu'à celui à partir duquel commence les valeur des champs. En effet, les fichiers sont formatés de tels sorte qu'entre le nom de champ le plus long et la valeure correspondante il n'y a qu'un seul espace.
    Les techniques employés jusque là ne sont pas parfaites et omettent forcément une valeur (car comprise dans un nom de champ)

    Le script devra donc compter à partir du premier caractère de la première ligne, continuer à compter pendant les espaces consécutif et s'arréter lorsqu'il revient sur un caractère différent de l'espace.

    Même si la syntaxe est plutôt rebutante pour un débutant, les traitements étaient jusque là plutôt simples.

    J'affecte des variables booléennes a mes deux derniers caractères et à mon caractère actuel (vrai si espace, faux si <> de espace)
    je doit avoir n-2=vrai et n-1=vrai et n=faux pour espace&espace&pas_espace
    alors le numéro de caractère de n est celui qui m'intéresse.

    Un coup de main ?(pour compter les caractères)

  17. #17
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    "index" devrait suffir

    Je suis à l'écoute de vos remarques, suggestions.

    Merci à tous pour votre aide.

  18. #18
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Je dois être hermétique...

    voila un exemple qui me retourne le numéro d'un caractère d'une sous chaine :
    (en l'occurence : espace&espace&tout_caractère sauf_espace)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    chaine="bla blagon            pfpoffdfdfd"
     
    expr index "$chaine" "?????????"
    Je peut mettre n'importe quoi entre les deuxièmes guillemets, il me dit toujours : 4

  19. #19
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Citation Envoyé par jonathan1
    Je dois être hermétique...

    voila un exemple qui me retourne le numéro d'un caractère d'une sous chaine :
    (en locurence : espace&espace&tout_caractère sauf_espace)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    chaine="bla blagon            pfpoffdfdfd"
     
    expr index "$chaine" "?????????"
    Je peut mettre n'importe quoi entre les deuxièmes guillemets, il me dit toujours : 4

    Effectivement, assez hermétique
    ci-dessous, prend si ça t'intéresses :


    Fichier :

    bla_blagon____________pfpoffdfdfd
    bla___________________pfpoffdfdfd
    b_____________________pfpoffdfdfd


    Script :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    awk '
    {
    	match($0,/   */)
    	print "* Enreg "NR", RSTART, RLENGTH : "RSTART, RLENGTH
    } ' toto.txt
    Résultat :

    * Enreg 1, RSTART, RLENGTH : 11 12
    * Enreg 2, RSTART, RLENGTH : 4 19
    * Enreg 3, RSTART, RLENGTH : 2 21
    Loi de Murphy:
    La Théorie c'est quand ça ne marche pas mais que l'on sait pourquoi.
    La Pratique c'est quand ça marche mais qu'on ne sait pas pourquoi.
    Quand la théorie rejoint la pratique ça ne marche pas et on ne sait pas pourquoi.

  20. #20
    Membre régulier
    Inscrit en
    Décembre 2006
    Messages
    243
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 243
    Points : 120
    Points
    120
    Par défaut
    Bonjour,

    Effectivement, assez hermétique
    Je veux bien l'admettre, mais tu ne me propose pas de solutions avec "expr index"

    Merci quand même.

    J'utilise sous windows un logiciel développé sous unix, j'utilise donc un émulateur accompagné d'un "interpréteur" shell, mais je ne connais pas la "version" du shell utilisé.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Débutant] modif de fichier texte => ordonnancements
    Par membreComplexe12 dans le forum MATLAB
    Réponses: 11
    Dernier message: 22/02/2010, 21h59
  2. Création modification de fichiers texte
    Par thierrybatlle dans le forum WinDev
    Réponses: 4
    Dernier message: 04/04/2007, 15h37
  3. modification de fichier texte en batch
    Par ob1knob dans le forum Windows
    Réponses: 15
    Dernier message: 03/10/2006, 17h10
  4. Modification de fichier texte
    Par jiloup dans le forum C++
    Réponses: 3
    Dernier message: 28/12/2005, 19h28
  5. Modification de fichiers texte
    Par ratbiker dans le forum Langage
    Réponses: 3
    Dernier message: 21/11/2005, 20h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo