Précédent   Forum des professionnels en informatique > Systèmes > Linux > Applications > Shell
Shell Vos questions sur l'utilisation des commandes shell
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
Vieux 07/01/2010, 12h08   #1
Membre régulier
 
Inscription : mars 2007
Messages : 88
Détails du profil
Informations personnelles :
Âge : 38
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 88
Points : 83
Points : 83
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 :
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 :
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 :
1
2
3
4
5
 
s|
||g
s|</Requete>|</Requete>
|g
et dans un script ksh je fais un l'appel :
Code :
1
2
#!/bin/ksh
sed -f OneLine.sed file.dat > file.out
Quand je l'exécute je reçois l'erreur :
Code :
sed: Function s| cannot be parsed.
Si j'essaie de remplacer le LF par \n :
Code :
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 :
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 :
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 :
<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
rafuoner est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 13h22   #2
Membre habitué
 
Inscription : mai 2007
Messages : 138
Détails du profil
Informations personnelles :
Âge : 59

Informations forums :
Inscription : mai 2007
Messages : 138
Points : 108
Points : 108
Un petit awk:
Code :
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 :
awk -f formatreq.awk requetes.dat

Dernière modification par noooop ; 07/01/2010 à 14h02.
noooop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 13h25   #3
Expert Confirmé
 
Avatar de N_BaH
 
Inscription : février 2008
Messages : 1 897
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 1 897
Points : 3 677
Points : 3 677
Code :
tr -d '\n' < file.dat | sed 's/<\/Requete>/&\n/g' > file.out
N_BaH est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 13h33   #4
Nouveau Membre du Club
 
David
Inscription : avril 2009
Messages : 26
Détails du profil
Informations personnelles :
Nom : David
Âge : 40

Informations forums :
Inscription : avril 2009
Messages : 26
Points : 27
Points : 27
Salut rafuoner,

Avec while :

Code :
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
syjis est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 13h40   #5
Expert Confirmé
 
Homme
Inscription : septembre 2006
Messages : 2 255
Détails du profil
Informations personnelles :
Sexe : Homme

Informations forums :
Inscription : septembre 2006
Messages : 2 255
Points : 2 685
Points : 2 685
Code :
1
2
3
 
cat PATH_TO_FILE | tr -d '\n' | sed "s/<Requete>/\\
<Requete>/g"
ou utilisez awk

Dernière modification par JeitEmgie ; 07/01/2010 à 13h55.
JeitEmgie est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h00   #6
Membre chevronné
 
Inscription : septembre 2007
Messages : 685
Détails du profil
Informations personnelles :
Âge : 48
Localisation : Suisse

Informations forums :
Inscription : septembre 2007
Messages : 685
Points : 723
Points : 723
Alors utilisons awk:
Code :
awk 'BEGIN {ORS=""} {print; if ($0 == "</Requete>") print "\n"}' file_in > file_out
__________________
Un problème bien posé est déjà résolu (H. Bergson).
jmelyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h06   #7
Membre régulier
 
Inscription : mars 2007
Messages : 88
Détails du profil
Informations personnelles :
Âge : 38
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 88
Points : 83
Points : 83
@ 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 :
1
2
3
s|</Requete>|</Requete>\
|g
et dans mon code :
Code :
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
rafuoner est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h06   #8
Membre habitué
 
Inscription : mai 2007
Messages : 138
Détails du profil
Informations personnelles :
Âge : 59

Informations forums :
Inscription : mai 2007
Messages : 138
Points : 108
Points : 108
Toujours en awk:

Code :
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).
noooop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h10   #9
Membre régulier
 
Inscription : mars 2007
Messages : 88
Détails du profil
Informations personnelles :
Âge : 38
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 88
Points : 83
Points : 83
Citation:
Envoyé par noooop Voir le message
Toujours en awk:

Code :
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
rafuoner est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h29   #10
Membre chevronné
 
Inscription : septembre 2007
Messages : 685
Détails du profil
Informations personnelles :
Âge : 48
Localisation : Suisse

Informations forums :
Inscription : septembre 2007
Messages : 685
Points : 723
Points : 723
@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 :
awk '{printf("%s", $0); if ($0 == "</Requete>" ) print "\n"}' file.in > file.out
__________________
Un problème bien posé est déjà résolu (H. Bergson).
jmelyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h30   #11
Membre habitué
 
Inscription : mai 2007
Messages : 138
Détails du profil
Informations personnelles :
Âge : 59

Informations forums :
Inscription : mai 2007
Messages : 138
Points : 108
Points : 108
oops...oui tu as raison. Merci

Citation:
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.
noooop est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h37   #12
Membre régulier
 
Inscription : mars 2007
Messages : 88
Détails du profil
Informations personnelles :
Âge : 38
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 88
Points : 83
Points : 83
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 :
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 :
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 ;-)
rafuoner est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 14h55   #13
Membre chevronné
 
Inscription : septembre 2007
Messages : 685
Détails du profil
Informations personnelles :
Âge : 48
Localisation : Suisse

Informations forums :
Inscription : septembre 2007
Messages : 685
Points : 723
Points : 723
Oops à mon tour,

Tu as raison rafuoner, j'ai dégainé trop vite.
__________________
Un problème bien posé est déjà résolu (H. Bergson).
jmelyn est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2010, 16h45   #14
Membre habitué
 
Inscription : mai 2007
Messages : 138
Détails du profil
Informations personnelles :
Âge : 59

Informations forums :
Inscription : mai 2007
Messages : 138
Points : 108
Points : 108
en fait c'est print ""
noooop est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +1. Il est actuellement 03h13.


 
 
 
 
Partenaires

Hébergement Web