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

Shell et commandes GNU Discussion :

Conversion de fichier texte en enlevant des linefeed


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 90
    Par défaut Conversion de fichier texte en enlevant des linefeed
    Bonjour,

    Un problème qui n'a pas de solution ce n'est pas un problème...

    J'ai un fichier (file.dat) texte qui est une suite de xml :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    <Requete>
    <Valeur1>un</Valeur1>
    <Valeur2></Valeur2>
    <Valeur3>trois</Valeur3>
    </Requete>
    <Requete>
    <Valeur1>un</Valeur1>
    <Valeur2>deux</Valeur2>
    <Valeur3>trois</Valeur3>
    </Requete>
    Je voudrais créer un script qui me modifie le fichier pour qu'il ressemble à ceci (file.out) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <Requete><Valeur1>un</Valeur1><Valeur2></Valeur2><Valeur3>trois</Valeur3></Requete>
    <Requete><Valeur1>un</Valeur1><Valeur2>deux</Valeur2><Valeur3>trois</Valeur3></Requete>
    Evidemment la première chose qui m'est venu à l'esprit c'est 'sed'.

    J'ai donc créer un fichier de commande sed (OneLine.sed) qui contient ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    s|
    ||g
    s|</Requete>|</Requete>
    |g
    et dans un script ksh je fais un l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #!/bin/ksh
    sed -f OneLine.sed file.dat > file.out
    Quand je l'exécute je reçois l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed: Function s| cannot be parsed.
    Si j'essaie de remplacer le LF par \n :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    s|\n||g
    s|</Requete>|</Requete>\n|g
    pas d'erreur mais il ne traite pas "\n" comme étant un passage à la ligne. Il me rajoute simplement un 'n' comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <Requete>
    <Valeur1>un</Valeur1>
    <Valeur2></Valeur2>
    <Valeur3>trois</Valeur3>
    </Requete>n
    <Requete>
    <Valeur1>un</Valeur1>
    <Valeur2>deux</Valeur2>
    <Valeur3>trois</Valeur3>
    </Requete>n
    J'ai essayé aussi avec "^J"... marche pas non plus. L'horreur quoi.

    Mais pour avancer un peu j'ai essayé d'enlever les LF avec la commande tr puis de lancer un sed
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    OneLine.sed => 
    s|</Requete>|</Requete>\n|g
     
    script =>
    #!/bin/ksh
    tr -d '\n' < file.orig > file.tmp
    sed -f OneLine.sed file.tmp > file.out
    J'ai bien un file.tmp qui ressemble à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <Requete><Valeur1>un</Valeur1><Valeur2></Valeur2><Valeur3>trois</Valeur3></Requete><Requete><Valeur1>un</Valeur1><Valeur2>deux</Valeur2><Valeur3>trois</Valeur3></Requete>
    sans aucun passage à la ligne.

    Mais sed ne lit même pas le fichier file.tmp, et je me retrouve avec un file.out vide.
    En revanche si je rajoute manuellement un LF à la fin de file.tmp, il traite le fichier... Il semble qu'il faille donc au moins un LF pour que sed traite le fichier.

    Bref, j'ai essayé pas mal de chose, mais je n'arrive pas au résultat escompté...

    Une idée ?

    Merci

  2. #2
    Membre expérimenté
    Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Âge : 72
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2007
    Messages : 248
    Par défaut
    Un petit awk:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    {
    	if ($0 == "<Requete>") {
    		printf("%s", $0)
    	} else {
    		if ($0 == "</Requete>") {
    			print $0
    		} else {
    			printf("%s", $0);
    		}
    	}
    }
    Appel du script (en copiant/collant les lignes ci dessus dans un fichier formatreq.awk):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -f formatreq.awk requetes.dat

  3. #3
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 640
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 640
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tr -d '\n' < file.dat | sed 's/<\/Requete>/&\n/g' > file.out
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  4. #4
    Membre confirmé
    Inscrit en
    Avril 2009
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Avril 2009
    Messages : 26
    Par défaut
    Salut rafuoner,

    Avec while :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # Remise a blanc de la variable
    NEW_FIC=""
     
    # Lecture du fichier ligne par ligne
    while read LINE
    do
       if [ "$LINE" = '<Requete>' ]
       then
          NEW_FIC="$NEW_FIC \n $LINE"
       else
          NEW_FIC="$NEW_FIC $LINE"
        fi
    done < file.dat
    echo "$NEW_FIC" > file_traite.dat

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 962
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    cat PATH_TO_FILE | tr -d '\n' | sed "s/<Requete>/\\
    <Requete>/g"
    ou utilisez awk

  6. #6
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Alors utilisons awk:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk 'BEGIN {ORS=""} {print; if ($0 == "</Requete>") print "\n"}' file_in > file_out

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 90
    Par défaut
    @ noop, syjis & jmelyn :
    J'avais pensé écrire un petit perl ou un awk pour résoudre le problème, mais il me parait tellement évident qu'un sed doit être employé que je ne veux meme pas l'envisager (je sais, je sais, je suis tétu comme une mule).

    @ N_BaH & JeitEmgie :
    ça fonctionne pas chez moi. Comme je dis, il semble que sed aie besoin au moins d'un LF pour lire l'input. Bref après le tr -d '\n' sed ne lit plus rien.

    Ce que j'ai trouvé :
    en fait il faut "escaper" le LF dans le fichier sed.

    Pas moyen de faire cela en une seule commande SED.
    Il faut rajouter un LF à la fin du fichier tmp pour que sed le prenne en compte.

    Le OneLine.sed est donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    s|</Requete>|</Requete>\
    |g
    et dans mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #!/bin/ksh
    tr -d '\n' < file.dat > file.tmp
    echo "" >> file.tmp
    sed -f OneLine.sed file.tmp > file.out
    Le truc c'est que je me retrouve avec 2 LF d'affilé à la fin du fichier, mais c'est pas graaaaaf.

    Merci de votre aide à tous !

    PS : ma citation du début vient des Shadocks, j'avais oublié de préciser

  8. #8
    Membre expérimenté
    Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Âge : 72
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2007
    Messages : 248
    Par défaut
    Toujours en awk:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '{printf("%s", $0); if ($0 == "</Requete>" ) print}' file.in > file.out
    J'ai déjà eu des problème avec sed et LINE FEED (sous HP-UX).

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 90
    Par défaut
    Citation Envoyé par noooop Voir le message
    Toujours en awk:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '{printf("%s", $0); if ($0 == "</Requete>" ) print}' file.in > file.out
    J'ai déjà eu des problème avec sed et LINE FEED (sous HP-UX).
    Je suis sur HP-UX... Je sais que je ne suis pas dans le bon forum , mais pour du scripting, ce qui marche dans l'un fonctionne souvent dans l'autre.

    J'ai testé et approuvé ta solution. Tout en une ligne, plus facile

  10. #10
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    @noooop:

    Attention, petit problème dans ton programme awk: la commande print est équivalente à print $0, pas à print "\n". Le résultat est alors deux tags </Requete> en fin de chaque ligne. Il faudrait donc mettre explicitement print "\n". En tout cas pour Linux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '{printf("%s", $0); if ($0 == "</Requete>" ) print "\n"}' file.in > file.out

  11. #11
    Membre expérimenté
    Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Âge : 72
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2007
    Messages : 248
    Par défaut
    oops...oui tu as raison. Merci

    Je suis sur HP-UX... Je sais que je ne suis pas dans le bon forum , mais pour du scripting, ce qui marche dans l'un fonctionne souvent dans l'autre.
    Moi aussi pour traiter de l'XML avec sed, j'ai du créer un fichier avec un linefeed dedans. Et maintenant avant de traiter de l'XML je concatene ce fichier avec les appels a SED.

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 90
    Par défaut
    Citation Envoyé par jmelyn Voir le message
    @noooop:

    Attention, petit problème dans ton programme awk: la commande print est équivalente à print $0, pas à print "\n". Le résultat est alors deux tags </Requete> en fin de chaque ligne. Il faudrait donc mettre explicitement print "\n". En tout cas pour Linux.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '{printf("%s", $0); if ($0 == "</Requete>" ) print "\n"}' file.in > file.out
    exact c'est exact.
    Mais en mettant print "\n" on crée une ligne vide entre chaque xml.

    Bref ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    awk '{printf("%s", $0); if ($0 == "</Requete>" ) print ""}' file.in > file.out
    ou 
    awk '{printf("%s", $0); if ($0 == "</Requete>" ) printf "\n"}' file.in > file.out
    fonctionne à merveille et c'est suuuuuuuper rapide ;-)

  13. #13
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Oops à mon tour,

    Tu as raison rafuoner, j'ai dégainé trop vite.

  14. #14
    Membre expérimenté
    Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2007
    Messages
    248
    Détails du profil
    Informations personnelles :
    Âge : 72
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2007
    Messages : 248
    Par défaut
    en fait c'est print ""

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 07/01/2010, 13h29
  2. Réponses: 2
    Dernier message: 24/05/2008, 10h14
  3. Réponses: 9
    Dernier message: 11/09/2007, 23h47
  4. Réponses: 2
    Dernier message: 09/12/2006, 18h01
  5. [VB.NET] lecture fichier texte et détection des mots
    Par zouhib dans le forum Windows Forms
    Réponses: 25
    Dernier message: 01/06/2006, 09h12

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