OVH Cloud OVH Cloud

Transformation d'un fichier texte

19 réponses
Avatar
Jean NEMAR
Bjr,


(je ne sais pas si je poste dans le bon forum,
mais je ne sais pas exactement où publier ce message ...)

Soit un fichier texte (nviron 6000 lignes) :
texte1
texte2
texte3
...

Je souhaiterais le transformer en :
texte1;texte2;texte3;...
texten;texten+1;...

Les contraintes étant :
- les lignes ne doivent pas dépasser 255 caractères ;
- les "textes" ne peuvent pas être tronqués.

Si possible, sous Windows (script, powershell).
Mais pourquoi pas en shell Unix ...

Merci de votre aide.

--
J.N.

9 réponses

1 2
Avatar
Jacques Barathon [MS]
"Jacques Barathon [MS]" wrote in message
news:
"Jacques Barathon [MS]" wrote in message
news:
...

Petite amélioration, j'ai supprimé le besoin d'avoir un compteur dédié
pour la longueur de chaque ligne:

PS> gc oldfile.txt|%{$o=$ofs;$ofs=";";$a=@();$e=1}{if ("$a;$_".length -gt
255) {"$a";$a=@();$e=0};$a+=$_;$e=1}{if ($e) {"$a"};$ofs=$o}>newfile.txt


Allez, une dernière amélioration pour aujourd'hui: simplification du test
final pour afficher la dernière ligne si celle-ci fait moins de 255
caractères (la version précédente était boguée de toute façon):

PS> gc oldfile.txt|%{$o=$ofs;$ofs=";";$a=@()}{if ("$a;$_".length -gt 255)
{"$a";$a=@()};$a+=$_}{if ("$a".length) {"$a";$ofs=$o}}>newfile.txt

Même avertissement que précédemment: le code qui suit "PS>" ci-dessus est
à saisir sur une seule ligne.


Idem.

Jacques

Avatar
Fred
"Jacques Barathon [MS]" Grand Gourou PowerShell a écrit dans le message
de news:

PS> gc oldfile.txt|%{$o=$ofs;$ofs=";";$a=@()}{if ("$a;$_".length -gt
255) {"$a";$a=@()};$a+=$_}{if ("$a".length)
{"$a";$ofs=$o}}>newfile.txt


Impressionant !
C'est bien simple, en ouvrant le post, j'ai cru que c'était du rot13 :-D

--
Fred
http://www.cerber mail.com/?3kA6ftaCvT (enlever l'espace)

Avatar
Jacques Barathon [MS]
"Fred" wrote in message
news:
"Jacques Barathon [MS]" Grand Gourou PowerShell a écrit dans le message de
news:

PS> gc oldfile.txt|%{$o=$ofs;$ofs=";";$a=@()}{if ("$a;$_".length -gt 255)
{"$a";$a=@()};$a+=$_}{if ("$a".length) {"$a";$ofs=$o}}>newfile.txt


Impressionant !
C'est bien simple, en ouvrant le post, j'ai cru que c'était du rot13 :-D


rotfl tu veux dire :-)

Jacques


Avatar
Gilles LAURENT [MVP]
"Jean NEMAR" a écrit dans le message de
news:46977b50$0$27369$
| Bjr,

Bonsoir,

[...]
| Soit un fichier texte (environ 6000 lignes) :
| texte1
| texte2
| texte3
| ...
|
| Je souhaiterais le transformer en :
| texte1;texte2;texte3;...
| texten;texten+1;...
|
| Les contraintes étant :
| - les lignes ne doivent pas dépasser 255 caractères ;
| - les "textes" ne peuvent pas être tronqués.

Uniquement pour le Fun, wacances oblige ;-)
Une version alternative en VBScript :

+++ Usage
worker.vbs <[path]filename>

+++ Exemple
cscript //nologo worker.vbs D:Testoldfile.txt > newfile.txt

--- Coupez ici : worker.vbs ---
Set oFs=CreateObject("Scripting.FileSystemObject")
Set oFile=oFs.OpenTextFile(WScript.Arguments(0))
str=Join(Split(oFile.ReadAll,VBCrLf),";")
Set oRe=New RegExp:oRe.Global=True:oRe.Pattern="(.{0,255});"
For Each oMatch In oRe.Execute(str)
WScript.Echo oMatch.SubMatches(0)
Next
--- Coupez ici : worker.vbs ---

Note: Je consulte le fil au fur et à mesure :-)

Note: Jacques, la version PS est quand même tip-top :-)

--
Gilles LAURENT [MVP]
http://glsft.free.fr
Avatar
Jacques Barathon [MS]
"Gilles LAURENT [MVP]" wrote in message
news:
...
Uniquement pour le Fun, wacances oblige ;-)
Une version alternative en VBScript :

+++ Usage
worker.vbs <[path]filename>

+++ Exemple
cscript //nologo worker.vbs D:Testoldfile.txt > newfile.txt

--- Coupez ici : worker.vbs ---
Set oFs=CreateObject("Scripting.FileSystemObject")
Set oFile=oFs.OpenTextFile(WScript.Arguments(0))
str=Join(Split(oFile.ReadAll,VBCrLf),";")
Set oRe=New RegExp:oRe.Global=True:oRe.Pattern="(.{0,255});"
For Each oMatch In oRe.Execute(str)
WScript.Echo oMatch.SubMatches(0)
Next
--- Coupez ici : worker.vbs ---


Gilles,

Excellente application des expressions régulières. Mais il y a un bug dans
ta version: le texte correspondant à la dernière ligne du fichier n'est pas
affiché.

Si je comprends bien, l'expression ne prend que ce qui se termine par un
point-virgule. Il faudrait soit "artificiellement" ajouter un point-virgule
à la fin (et le retirer ensuite) soit construire une expression régulière
qui accepte à la fois le point-virgule et la fin de ligne ($). Je te laisse
travailler à ça comme devoir de vacances! ;-)

Jacques

Avatar
Gilles LAURENT [MVP]
"Jacques Barathon [MS]" a écrit dans le
message de
news:%

Bonjour Jacques,

| Excellente application des expressions régulières. Mais il y a un bug
| dans ta version: le texte correspondant à la dernière ligne du
| fichier n'est pas affiché.
[...]

En effet, ce problème apparait si la dernière ligne du fichier source ne
se termine pas par la séquence CRLF. Pour résoudre ce problème sans
devoir effectuer de test sur la présence ou non du caractère de
séparation (point-virgule) à chaque itération, une solution consiste à
supprimer tous les caractères de séparation situés en fin de chaîne et
d'adapter l'expression régulière pour accepter également la fin de ligne
($) comme tu le suggère. Cette technique permet de ne pas embarquer le
point-virgule final avec l'expression régulière en mode Greedy.

--- Coupez ici : worker.vbs ---
Set oFs=CreateObject("Scripting.FileSystemObject")
Set oFile=oFs.OpenTextFile(WScript.Arguments(0))
str=Join(Split(oFile.ReadAll,VBCrLf),";")
Set oRe=New RegExp:oRe.Global=True
oRe.Pattern=";*$":str=oRe.Replace(str,"")
oRe.Pattern="(.{0,255})(;|$)"
For Each oMatch In oRe.Execute(str)
WScript.Echo oMatch.SubMatches(0)
Next
--- Coupez ici : worker.vbs ---

Note: Le fichier source peut maintenant se terminer par 0, 1 ou N
séquences CRLF sans perturbation ;-)

--
Gilles LAURENT [MVP]
http://glsft.free.fr
Avatar
Jacques Barathon [MS]
"Gilles LAURENT [MVP]" wrote in message
news:
"Jacques Barathon [MS]" a écrit dans le
message de
news:%
...

--- Coupez ici : worker.vbs ---
Set oFs=CreateObject("Scripting.FileSystemObject")
Set oFile=oFs.OpenTextFile(WScript.Arguments(0))
str=Join(Split(oFile.ReadAll,VBCrLf),";")
Set oRe=New RegExp:oRe.Global=True
oRe.Pattern=";*$":str=oRe.Replace(str,"")
oRe.Pattern="(.{0,255})(;|$)"
For Each oMatch In oRe.Execute(str)
WScript.Echo oMatch.SubMatches(0)
Next
--- Coupez ici : worker.vbs ---

Note: Le fichier source peut maintenant se terminer par 0, 1 ou N
séquences CRLF sans perturbation ;-)


Très intéressant. Je vais devoir me mettre à une étude approfondie des
expressions régulières pour mes propres vacances car il y a des subtilités
qui m'échappent encore... en adaptant ton script en PowerShell, je suis
obligé d'inverser la séquence: d'abord la recherche de chaînes faisant entre
0 et 255 caractères, et ensuite la suppression du point-virgule final
éventuel.

--- coupez ici : worker.ps1 ---
$lignes = [string]::join(";",(gc $args[0]))
$lignes = [regex]::matches($lignes,"(.{0,255})(;|$)")
$lignes | foreach {$_.value -replace ";*$",""}
--- coupez ici : worker.ps1 ---

Jacques

Avatar
Jacques Barathon [MS]
"Jacques Barathon [MS]" wrote in message
news:
...
Très intéressant. Je vais devoir me mettre à une étude approfondie des
expressions régulières pour mes propres vacances car il y a des subtilités
qui m'échappent encore... en adaptant ton script en PowerShell, je suis
obligé d'inverser la séquence: d'abord la recherche de chaînes faisant
entre 0 et 255 caractères, et ensuite la suppression du point-virgule
final éventuel.


Bon, voici déjà une version qui peut se passer du remplacement/suppression
du point-virgule final. Du coup, je l'ai regroupée en une seule ligne, pour
le fun (à recoller si c'est tronqué à l'affichage):

--- couper ici ---
[regex]::matches([string]::join(";",(gc
$args[0])),"(?<=;|^).{0,255}(?=;|$)")|%{$_.value}
--- couper ici ---

Mais bon, si on veut y comprendre quelque chose, on l'éclatera plutôt en
trois lignes:

--- couper ici ---
$fichier = [string]::join(";",(get-content $args[0]))
$lignes = [regex]::matches($fichier,"(?<=;|^).{0,255}(?=;|$)")
$lignes | foreach {$_.value}
--- couper ici ---

Jacques

Avatar
Gilles LAURENT [MVP]
"Jacques Barathon [MS]" a écrit dans le
message de
news:
| "Jacques Barathon [MS]" wrote in
| message news:
| ...
|| Très intéressant. Je vais devoir me mettre à une étude approfondie
|| des expressions régulières pour mes propres vacances car il y a des
|| subtilités qui m'échappent encore... en adaptant ton script en
|| PowerShell, je suis obligé d'inverser la séquence: d'abord la
|| recherche de chaînes faisant entre 0 et 255 caractères, et ensuite
|| la suppression du point-virgule final éventuel.
|
| Bon, voici déjà une version qui peut se passer du
| remplacement/suppression du point-virgule final. Du coup, je l'ai
| regroupée en une seule ligne, pour le fun (à recoller si c'est
| tronqué à l'affichage):
|
| --- couper ici ---
| [regex]::matches([string]::join(";",(gc
| $args[0])),"(?<=;|^).{0,255}(?=;|$)")|%{$_.value}
| --- couper ici ---

Super !
Tu peux donc répondre à Fred que tu le tiens ton oneliner :-)

--
Gilles LAURENT [MVP]
http://glsft.free.fr
1 2