[RESOLU] Batch - copier des parties d'un fichier texte

Batch - copier des parties d'un fichier texte [RESOLU] - Shell/Batch - Programmation

Marsh Posté le 31-03-2015 à 11:48:05    

Bonjour,
 
Je désire transformer un document texte en le recopiant et en le réaménageant suivant le nombre de caractère.
Je m'explique :
j'ai un document txt fait ainsi
 
Nom1        Nom2       Nom3
adresse1   Adresse2   Adresse3
Ville1        Ville2        Ville3
 
Nom4        Nom5       Nom6
adresse4   adresse5  adresse6
Ville4        Ville5       Ville6
 
et je désire le recopier dans un fichier csv en triant les données par colonne :
Nom1;adresse1;Ville1
Nom2;adresse2;Ville2
Nom3;adresse3;Ville3
Nom4;adresse4;Ville4
Nom5;adresse5;Ville5
Nom6;adresse6;Ville6
 
Bien sur le il y a beaucoup plus de ligne.
 
Chaque partie de mon texte d'origine ont toujours la même taille (37 caratères) et il y a toujours 7 caractères entre 2 parties :
Nom1 fait 37 caractères et il y a 7 caractères entre nom1 et nom2.
 
Quelle commande peut me permettre de récupérer les 37 premiers caractères de la ligne 1 puis des 44eme au 81eme caractère ...
et en faire une concaténation
 
Merci d'avance pour vos idées
 
Bonne journée


Message édité par stpre le 07-04-2015 à 11:38:49
Reply

Marsh Posté le 31-03-2015 à 11:48:05   

Reply

Marsh Posté le 31-03-2015 à 16:32:23    

Bonjour,
Il va te falloir utiliser un langage de script comme perl, python voire awk.
 
En perl, un script comme celui ci ferait le boulot, au vu de tes specs.
 

Code :
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. my @block;
  7. open my $fhin, "<", "lines.txt";
  8. open my $fhout, ">", "lines1.txt";
  9. while (<$fhin> ) {
  10.  my (@nom, @adresse, @ville);
  11.  chop;
  12.  push @block, $_;
  13.  # si on a lu quatre lignes
  14.  if (@block == 4 || eof) {
  15.    # si le contenu a le bon pattern on range les 3 valeurs dans un tableau ad-hoc (ici @nom)
  16.    if (defined($block[0]) && ($block[0] =~ /^(.{37})\s{7}(.{37})\s{7}(.{37})\s*$/)) {
  17.      push @nom, $1, $2, $3;
  18.      map {s/^\s+|\s+$//g} @nom; # vire les blancs en trop autour le cas échéant
  19.    } else {
  20.      die "ligne de noms incorrecte: $block[0]!";
  21.    }
  22.    if (defined($block[1]) && ($block[1] =~ /^(.{37})\s{7}(.{37})\s{7}(.{37})\s*$/)) {
  23.      push @adresse, $1, $2, $3;
  24.      map {s/^\s+|\s+$//g} @adresse;
  25.    } else {
  26.      die "ligne d'adresse incorrecte: $block[1]!";
  27.    }
  28.    if (defined($block[2]) && ($block[2] =~ /^(.{37})\s{7}(.{37})\s{7}(.{37})\s*$/)) {
  29.      push @ville, $1, $2, $3;
  30.      map {s/^\s+|\s+$//g} @ville;
  31.    } else {
  32.      die "ligne de ville incorrecte: $block[2]!";
  33.    }
  34.    if (defined($block[3]) && ($block[3] !~ /^\s*$/)) {
  35.      die "ligne de separation incorrecte: $block[3]!";
  36.    }
  37.    # on imprime maintenant dans l'ordre voulu
  38.    foreach my $i (0..2) {
  39.      print $fhout "$nom[$i];$adresse[$i];$ville[$i]\n";
  40.    }
  41.    # raz pour traiter le prochain groupe de 4 lignes
  42.    @block = ();
  43.  }
  44. }
  45. close $fhout;
  46. close $fhin;


 
A+,


Message édité par gilou le 31-03-2015 à 16:36:32

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 03-04-2015 à 12:09:37    

Merci Gilou pour ta proposition en perl.
 
Je pense que le perl doit proposer beaucoup plus de possibilité mais je ne connais pas ce language pour l'instant et n'ai pas le temps de de l'appréhender pour mon script.
 
Je travaille actuellement sur un code en batch qui j’espère fera l'affaire.
 
Bonne journée

Reply

Marsh Posté le 03-04-2015 à 13:46:03    

Vu que le batch n'est absolument pas adapté à ce genre de choses, bon courage!
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 07-04-2015 à 11:37:38    

Bonjour,
 
J'ai finalement réussi à faire mon script en batch.
 
Si ça intéresse quelqu'un, je le posterai
 
Bonne journée

Reply

Marsh Posté le 07-04-2015 à 11:42:34    

Oui, n'hésites pas à le poster, découper ta ligne en champs, en batch c'est complexe mais faisable, ce qui m'intéresserait c'est de voir comment tu t'es débrouillé pour lire tes lignes par blocs de 3 ou 4.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 07-04-2015 à 14:48:34    

Dans l'exemple que j'avais mis sur mon 1er message, j'indiquais que le document d'origine était fait comme ca
Nom1  
adresse1  
Ville1  
 
Mais en fait, les champs nom, prenom et adresse sont sur 7 lignes. mais il y a bien 3 colonnes de données
 
Voici le code un peu commenté
 

Code :
  1. echo off
  2. cls
  3. echo la recuperation des donnees est en cours - veuillez patienter.
  4. echo off
  5. set VResult=result-etiquette.csv
  6. set VModel=Modele-etiquette.odt
  7. if exist %VResult% del %VResult%
  8. echo Lign1;Lign2;Lign3;Lign4;Lign5;Lign6;Lign7 >>%VResult%
  9. :: Initialisation des variables
  10. set VTexte=test.txt
  11. set VNumPaq=4
  12. set VNumligne=%VNumPaq%
  13. set VNumChamp=0
  14. :recupligne
  15. set /a VNumChamp+=1
  16. set VAffLigne=
  17. :: Recuperation de la ligne n° VNumLigne dans la variable VAffLigne
  18. for /F "delims=" %%a in ('findstr /n "^" %VTexte% ^| findstr "^%VNumligne%:"') do set VAffLigne=%%a
  19. :: Recuperation des blocs de données dans la ligne récupéré au dessus
  20. :: le point après l'echo permet de gerer les blocs vides
  21. :: je dois décalé mes blocs de 2, 3 ou 4 caratères car la commande findstr ajoute le n° de ligne au début
  22. if %VNumLigne% LEQ 9 (for /F "delims=" %%b in ('echo.%VAffLigne:~2,41%') do set VL%VNumChamp%1=%%b
  23. goto :suite1)
  24. if %VNumLigne% LEQ 99 (for /F "delims=" %%b in ('echo.%VAffLigne:~3,41%') do set VL%VNumChamp%1=%%b
  25. goto :suite1)
  26. if %VNumLigne% LEQ 999 (for /F "delims=" %%b in ('echo.%VAffLigne:~4,41%') do set VL%VNumChamp%1=%%b
  27. goto :suite1)
  28. if %VNumLigne% GEQ 1000 (for /F "delims=" %%b in ('echo.%VAffLigne:~5,41%') do set VL%VNumChamp%1=%%b)
  29. :suite1
  30. if %VNumLigne% LEQ 9 (for /F "delims=" %%c in ('echo.%VAffLigne:~46,41%') do set VL%VNumChamp%2=%%c
  31. goto :suite2)
  32. if %VNumLigne% LEQ 99 (for /F "delims=" %%c in ('echo.%VAffLigne:~47,41%') do set VL%VNumChamp%2=%%c
  33. goto :suite2)
  34. if %VNumLigne% LEQ 999 (for /F "delims=" %%c in ('echo.%VAffLigne:~48,41%') do set VL%VNumChamp%2=%%c
  35. goto :suite2)
  36. if %VNumLigne% GEQ 1000 (for /F "delims=" %%c in ('echo.%VAffLigne:~49,41%') do set VL%VNumChamp%2=%%c)
  37. :suite2
  38. if %VNumLigne% LEQ 9 (for /F "delims=" %%d in ('echo.%VAffLigne:~90,41%') do set VL%VNumChamp%3=%%d
  39. goto :suite3)
  40. if %VNumLigne% LEQ 99 (for /F "delims=" %%d in ('echo.%VAffLigne:~91,41%') do set VL%VNumChamp%3=%%d
  41. goto :suite3)
  42. if %VNumLigne% LEQ 999 (for /F "delims=" %%d in ('echo.%VAffLigne:~92,41%') do set VL%VNumChamp%3=%%d
  43. goto :suite3)
  44. if %VNumLigne% LEQ 9999 (for /F "delims=" %%d in ('echo.%VAffLigne:~93,41%') do set VL%VNumChamp%3=%%d)
  45. :suite3
  46. :: Je vérifie si j'arrive au bout d'un bloc de 7 lignes
  47. :: si c'est le cas, je lance la copie des donnees dans mon fichier result, sinon, je continue à récuperer les blocs de données
  48. set /a VNumligne+=1
  49. set /a VComp=%VNumPaq%+6
  50. If %VNumligne% LEQ %VComp% goto :recupligne
  51. :: Copie des blocs de données remis dans l'ordre dans le fichier résultat
  52. echo %VL11%;%VL21%;%VL31%;%VL41%;%VL51%;%VL61%;%VL71% >>%VResult%
  53. echo %VL12%;%VL22%;%VL32%;%VL42%;%VL52%;%VL62%;%VL72% >>%VResult%
  54. echo %VL13%;%VL23%;%VL33%;%VL43%;%VL53%;%VL63%;%VL73% >>%VResult%
  55. :: Vidage des variables sinon si une ligne est vide la variable conserve l'ancienne valeur
  56. for /L %%N in (11,1,73) do set VL%%N=
  57. :: Mise à jour des variables
  58. set /a VNumPaq+=9
  59. set /a VNumligne=%VNumPaq%
  60. set /a VNumChamp=0
  61. set VAffLigne2=
  62. set VLvide=
  63. :: Controle de la fin du texte. Si la ligne a traité est vide alors arret de la commande
  64. for /F "delims=" %%z in ('findstr /n "^" %VTexte% ^| findstr "^%VNumligne%:"') do set VAffLigne2=%%z
  65. for /F "delims=" %%y in ('echo.%VAffLigne2:~5,36%') do set VLvide=%%y
  66. If "%VLvide%" EQU "" goto :fin
  67. goto :recupligne
  68. :fin
  69. "C:\Program Files\LibreOffice 3.5\program\swriter.exe" %VModel%


 

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed