Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
621 connectés 

  FORUM HardWare.fr
  Programmation
  Shell/Batch

  Shell : Découper un fichier en plusieurs fichiers

 



 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Shell : Découper un fichier en plusieurs fichiers

n°1934219
sushi4556
Posté le 21-10-2009 à 15:20:55  profilanswer
 

Bonjour,
voici mon problème:
 
j'ai un fichier person.txt dans lequel se trouve ces lignes:
 
<person>
<id>158</id>
<nom>Toto</nom>
<ville>Paris</ville>
</person>
 
<person>
<id>19521</id>
<nom>Mama</nom>
<ville>Bordeaux</ville>
</person>
 
<person>
<id>75142</id>
<nom>Kaka</nom>
<ville>Rennes</ville>
</person>
 
 
les <id>xxxxx</id> peut être n'importe quelle chiffre mais il y a "<id>xxxxx</id>" = N fois.
je voudrais découper ce fichier en N fichiers: fichier "person158" dans lequel se trouve:
<id>158</id>
<nom>Toto</nom>
<ville>Paris</ville>
 
Fichier "person19521" dans lequel se trouve
<id>19521</id>
<nom>Mama</nom>
<ville>Bordeaux</ville>
et ainsi de suite...
 
Je voudrais créer des fichiers .txt (person158.txt, person19521.txt ...) dans lesquelles
se trouvent les informations correspondants.
Dans "person158.txt" il y aura
 
<id>158</id>
<nom>Toto</nom>
<ville>Paris</ville>
 
dans "person19521.txt" il y aura
 
<id>19521</id>
<nom>Mama</nom>
<ville>Bordeaux</ville>
 
et ainsi de suite.
 
Il faut donc dans le fichier de départ rechercher les <id>xxxxx</id>, avec ces noms créer des fichiers "personxxxxx.txt"
et dans "personxxxxx.txt"  il faut copier les lignes se trouvant dans le fichier principal.  
 
je suis débutant en shell  
 
Help me please!!!!
merci


Message édité par sushi4556 le 21-10-2009 à 15:22:02
mood
Publicité
Posté le 21-10-2009 à 15:20:55  profilanswer
 

n°1934239
pataluc
Posté le 21-10-2009 à 16:01:00  profilanswer
 

vu que ton fichier en entrée ressemble fortement à du xml, l'idéal serait d'utiliser un parser xml...

 

mais sinon, en quick&dirty (et en supposant que tout le fichier soit structuré comme ton exemple au niveau des retours chariots et toussa) tu peux t'en sortir avec un joli awk:

Code :
  1. awk 'match($0, "<id>.*</id>" ) {a = $0;
  2. gsub("<id>", "", a);
  3. gsub("</id>", "", a);
  4. system("echo \""$0"\" >> person"a".txt" );
  5. getline;
  6. system("echo \""$0"\" >> person"a".txt" );
  7. getline;
  8. system("echo \""$0"\" >> person"a".txt" )
  9. }' t

(ou t est ton fichier)


Message édité par pataluc le 21-10-2009 à 16:02:20
n°1934265
sushi4556
Posté le 21-10-2009 à 16:36:40  profilanswer
 

Bonjour pataluc,
 
Premièrement, merci pour ta réponse, mais j'ai en fait N fichiers et pas seulement 3 fichiers. J'ai besoins donc de faire un boucle et c'est ici où je suis bloquée.
 
D'autre part, tu as parlé de "parser xml", peut-tu me donner quelques exemples s'il te plaît? Car cela sera la suite de mon boulot.  
 
Merci encore

n°1934270
sushi4556
Posté le 21-10-2009 à 16:52:06  profilanswer
 

En fait, j'avais fait :
 
#!/bin/ksh
 
FICIN="person.txt"
typeset -i compteur=1
 
while read ligne ; do
     echo "$ligne" >> ${FICIN%%.*}_${compteur}.xml
     if [ $(echo "$ligne" | egrep -n '</person>' | wc -l ) -eq 1 ]; then
                           ((compteur = compteur+1))
     fi
 
done <$FICIN

 
Mais leur nom ne correspond pas ce que je souhaite.
J'ai obtenu
 
person1.txt dans lequel je trouve
<person>
<id>158</id>
<nom>Toto</nom>
<ville>Paris</ville>
</person>  
 
person2.txt dans lequel je trouve
<person>
<id>19521</id>
<nom>Mama</nom>
<ville>Bordeaux</ville>
</person>  
 
et ainsi person3.txt .........
 
 
Mais je souhaite que le nom de ces fichiers soit "personxxxxx.txt" où xxxxx est le numéro id.


Message édité par sushi4556 le 21-10-2009 à 16:52:32
n°1934271
pataluc
Posté le 21-10-2009 à 16:54:23  profilanswer
 

as tu au moins essayé mon code? parce qu'il fonctionne quel que soit le nombre de fichiers (il y a 3 lignes, correspondant aux trois lignes id, nom et ville)...

 

et sinon pour les parser xml, google est ton ami... ^^ (il te faudra cependant lacher le ksh pour un langage type perl, python, java, etc)


Message édité par pataluc le 21-10-2009 à 16:56:09
n°1934283
lennelei
Posté le 21-10-2009 à 17:24:34  profilanswer
 

On a droit au perl ?

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. my $id;
  5. my $output_file;
  6. my $output;
  7. while(<> ) {
  8.         if (/<id>(\d+)<\/id>/) {
  9.                 $id=$1;
  10.                 $output=$_;
  11.         } elsif (/<\/person>/) {
  12.                 open $output_file, '>', "person$id.txt" or die("person$id.txt: $!" );
  13.                 print $output_file $output;
  14.                 close $output_file;
  15.         } elsif (! /^\s+$/) {
  16.                 $output.=$_;
  17.         }
  18. }
 

Usage :

perl split.pl person.txt

 

Fonctionne quelque soit le contenu du fichier source (s'il y a 10 lignes pour une personne, ça marche) : ressort tout ce qui est compris entre un <id>xxxx</id> et </person> (</person> non compris) dans un fichier personxxxx.txt

 

Peut être adapté pour prendre en compte des espaces dans la ligne <id>xxxx</id> si besoin.

 

edit: ça n'est pas non plus un parser, mais bon, il permet de gérer plusieurs lignes =) et puis j'aime bien perl...


Message édité par lennelei le 21-10-2009 à 17:30:01
n°1934292
lennelei
Posté le 21-10-2009 à 17:53:54  profilanswer
 

Sinon, ton idée était bonne, il suffit de récupérer l'id pour nommer le fichier plutôt que d'utiliser un compteur :

 
Code :
  1. #!/bin/ksh
  2. FICIN="person.txt"
  3. typeset -i compteur=0
  4. while read ligne ; do
  5.      if [ $(echo "$ligne" | egrep '<id>' |cut -d'>' -f2 |cut -d'<' -f1 | wc -l ) -eq 1 ]; then
  6.         (( compteur = $(echo "$ligne" | egrep '<id>' |cut -d'>' -f2 |cut -d'<' -f1 ) ))
  7.      fi
  8.      if [ $(echo "$ligne" | egrep -n '</person>' | wc -l ) -eq 1 ]; then
  9.         ((compteur = 0))
  10.      fi
  11.      echo "$ligne" >> ${FICIN%%.*}_${compteur}.xml
  12. done <$FICIN
 

A noter qu'un fichier person_0.txt est créé et contient toutes les lignes que tu ne prends pas (<person> et </person> et les lignes entre par exemple), c'est pour ça que le echo est à la fin.


Message édité par lennelei le 21-10-2009 à 17:54:28
n°1934408
pataluc
Posté le 22-10-2009 à 10:10:36  profilanswer
 

pourquoi faire en 16 ligne et je ne sais combien de commandes ce qui se fait un un seul awk de moitié moins de lignes? (je fais abstraction des sous commandes system passées dans le awk)
 
 :whistle:


Message édité par pataluc le 22-10-2009 à 10:10:49
n°1934495
lennelei
Posté le 22-10-2009 à 12:45:17  profilanswer
 

Parce qu'au départ, elle partait d'un ksh et qu'après réflexion, je me suis dit qu'on pouvait le faire en ksh sans utiliser awk ou perl.
Donc plutôt que de lui filer uniquement une solution en perl/awk, je lui montre comment faire à partir de ce qu'elle a écrit, c'est plus formateur que de balancer 20 lignes de codes en perl ou awk si elle ne connait pas perl / awk ? (oui, je sais, elle a intérêt à l'apprendre un jour =)

 


Message édité par lennelei le 22-10-2009 à 12:45:31

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Shell/Batch

  Shell : Découper un fichier en plusieurs fichiers

 

Sujets relatifs
[html] Problème sur un formulaire avec plusieurs boutons submitTexte en couleur (console)
Erreur d'uploader un fichier en PHPChoisir plusieurs fichiers pour un htaccess?
[resolu] Formulaire avec upload qui renomme mon fichier[help] copie de fichier et renomage si doublon
Programmation script shell ksh unixPrendre la valeur après un ping
[Résolu][JSF]Télécharger fichier CSV depuis un flux 
Plus de sujets relatifs à : Shell : Découper un fichier en plusieurs fichiers


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR