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

Scripts/Batch Discussion :

Mise en format de tableaux d'un fichier txt [PowerShell]


Sujet :

Scripts/Batch

  1. #1
    Membre actif
    Avatar de troxsa
    Inscrit en
    Novembre 2004
    Messages
    386
    Détails du profil
    Informations personnelles :
    Âge : 50

    Informations forums :
    Inscription : Novembre 2004
    Messages : 386
    Points : 264
    Points
    264
    Par défaut Mise en format de tableaux d'un fichier txt
    Bonjour,

    J'ai un gros fichier texte (7 Mo) avec divers tableaux au format, voici a quoi ça ressemble :

    Nom : Capturevvv.PNG
Affichages : 1592
Taille : 5,1 Ko

    L'idée est faire la récupération de tous les tableaux qui se trouvent dans le fichier texte en ArrayList (tableau).
    Existerait-il un moyen simple avec powershell ?


    En vous remerciant d'avance

  2. #2
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2014
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2014
    Messages : 257
    Points : 397
    Points
    397
    Par défaut
    Là tout de suite je ne saurais te répondre mais. As-tu, dans ton fichier, à chaque fois le même nombre de colonnes et surtout un séparateur bien défini par tableau ?

    De plus, ne pourrais-tu pas spliter ton fichier en plusieurs pour avoir plein de "petits fichiers" ne contenant qu'un tableau chacun ?

  3. #3
    Membre actif
    Avatar de troxsa
    Inscrit en
    Novembre 2004
    Messages
    386
    Détails du profil
    Informations personnelles :
    Âge : 50

    Informations forums :
    Inscription : Novembre 2004
    Messages : 386
    Points : 264
    Points
    264
    Par défaut
    Bonjour JeanYvette,

    Non il peut y avoir plusieurs lignes et plusieurs colonnes de taille différentes, le fichier log avec les tableaux dedans sont générés par des recettes DB2 (SQL), il y a chaque fois différente taille.

    Votre idée serait de faire une lecture du fichier (ligne par ligne ?) pour en faire des petits fichiers contenant uniquement les tableaux ?

  4. #4
    Membre averti
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2014
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2014
    Messages : 257
    Points : 397
    Points
    397
    Par défaut
    Oui ca serait exactement mon idée, ainsi le script parcourrait des fichiers constitués à 100% de tableaux et ainsi, en fonction du besoin, soit générer un tableau global soit pouvoir adapter à du cas par cas si besoin

    Après pour cette solution, il faut pouvoir distinguer tableau et texte



    Sinon, avez-vous la main sur vos scripts/requêtes SQL qui génèrent les fichiers ? Les modifier/adapter n'est pas imaginable ?

  5. #5
    Membre actif
    Avatar de troxsa
    Inscrit en
    Novembre 2004
    Messages
    386
    Détails du profil
    Informations personnelles :
    Âge : 50

    Informations forums :
    Inscription : Novembre 2004
    Messages : 386
    Points : 264
    Points
    264
    Par défaut
    Le script (plutôt la requête DB2) génère automatique le log en mettant en forme des tableaux, cela n'est donc pas possible.

    Peut-être que votre idée reste la meilleurs faute de n'avoir rien d'autre

    Donc, lecture du fichier ligne par ligne, je détecte si la ligne contient une "===========" (trim() + split ou replace par ";") supérieure a 2 et je récupérer la ligne de dessus pour avoir le nom des colonnes.
    Puis je fais la lecture des autres lignes jusqu’à a avoir une ligne vide pour avoir un tableau complet.

    c'est complément possible et plutôt facile a faire je pense.
    Qu'en pensez vous ?

  6. #6
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Salut,
    Citation Envoyé par troxsa Voir le message
    Qu'en pensez vous ?
    Si tu sais comment déterminer le début et la fin d'un tableau ( le split proposé par JeanYvette) c'est tout à fait possible.
    Le principe suivant, via le pipeline, peut être utilisé :
    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    Filter Remove-AuthenticodeSignature{
    #([Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding] $Encoding="ASCII")
     
     
       function Parse([String] $FileName)
       { #renvoi toutes les lignes sauf celles du bloc de signature
         $isSignatureBloc=$False
         Get-Content -Path $FileName|
         Foreach-Object { 
           switch ($_)  
           {
             "# SIG # Begin signature block"  {$isSignatureBloc=$True;continue}
             "# SIG # End signature block"    {$isSignatureBloc=$False;Continue}
     
             default {
               if ($isSignatureBloc -eq $false)
                  #On traite les lignes qui ne se trouvent pas dans le bloc de signature 
                {$_}
             }#default
          }#Switch
         }#Foreach
       }#Parse
     
     if ($_ )
     {  
       #Récupére un nom de fichier créé par l'OS
      $TempFile = [IO.Path]::GetTempFileName()
      $FullPath=Resolve-Path "$_"
      Write-Debug "$TempFile"
      Write-Debug "$FullPath" 
     
     
       #Extrait toutes les lignes sauf la signature dans un fichier temporaire 
      Parse "$FullPath"|Set-Content "$TempFile"
     
       #Ecrase le fichier d'origine à partir du fichier temporaire
       #$FileInfo.Replace ne fonctionne pas car %Temp% 
       #peut être sur un disque différent de celui de la source :/ 
      Get-Content "$TempFile"|Set-Content "$FullPath" 
      Remove-Item "$TempFile" 
     }
     else {Write-Error "[Remove-AuthenticodeSignature] Ce filtre a reçu une donnée `$null du pipeline."}
    }
    (Un filtre est une fonction ayant uniquement un bloc process, là où une fonction basique n'a qu'un bloc end. Une fonction avancée pouvant implémenter les trois blocs : begin, process et end)

    J'avais crée une fonction d'analyse générique, mais pour des structures ayant un nombre de ligne fixe.
    Envisager peut être un mixte avec Convert-String
    De prime abord je pense qu'il y aura deux passes.

  7. #7
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Une ébauche avec un exemple de texte à analyser où le découpage des tableaux est simple à déterminer :
    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
    $file='c:\temp\lines'
    @'
    Nom1 Nom2 Nom3
    ==============
    Col1 Col2 Col3
    Col1 Col2 Col3
     
    Nom1 Nom2 Nom3 Nom4
    ===================
    Col1 Col2 Col3 Col4
    Col1 Col2 Col3 Col4
     
    Nom1 Nom2
    =========
    Col1 Col2
    Col1 Col2
    '@ > $file
     
     
    $DebugPreference='Continue'
    $isInsideArray=$False
    $CurrentArray=[System.Collections.ArrayList]::new()
     
    $Precedent=$null
    $Arrays=[System.Collections.ArrayList]::new()
     
    Foreach ($line in Get-Content -Path $file)
    {
        switch -regex ($Line) {
            '={3,}'  { 
                        Write-Debug "Début de tableau, ajoute le header '$Precedent'"
                        $isInsideArray=$True
                        $CurrentArray.Add($Precedent) > $null
                        continue 
                     }
            '^$'     { 
                        $Count=$CurrentArray.count 
                        if ($Count -gt 0)
                        {
                            Write-Debug "Fin de tableau on le mémorise. Il contient '$Count' élément(s)"
                            $isInsideArray=$False
                            $Arrays.Add(@(,$CurrentArray)) > $null
                            Write-Debug "`tNouvel objet tableau"
                            $CurrentArray=[System.Collections.ArrayList]::new()
                            Write-Debug "`tRAZ du header"
                            $Precedent=$null
                        }
                        Continue
                     }
     
            default {
              if ($isInsideArray)
              { 
                if (-not ($Line.Trim() -eq [string]::Empty) )
                {
                   Write-Debug "`tAjoute la ligne '$line'"
                   $CurrentArray.Add($line) > $null
                }
              }
              elseif ($null -eq $precedent) 
              { 
                 Write-Debug "Mémorise le header '$line'"
                 $Precedent=$line 
              }
            }#default
        }#Switch
    }#Foreach
    Write-Debug "Mémorise le dernier tableau qui  contient '$($CurrentArray.count)' élément(s)"
    $Arrays.Add(@(,$CurrentArray)) >$null
     
    $Arrays.count
    $Arrays[0][0]
     
     
    foreach ($T in $Arrays)
    {
       foreach ($Current in $T)
       {
         $Csv=foreach ($Line in $Current )
         { 
            $Line.Trim() -Replace ' ',';' 
         }
         Write-warning "`r`n$($Csv|out-string)"
       }
    }
    Reste qu'avec cette approche, dés que l'on ajoute des lignes entre les tableaux, de déterminer la fin de chaque est plus 'difficile' :-)

  8. #8
    Membre actif
    Avatar de troxsa
    Inscrit en
    Novembre 2004
    Messages
    386
    Détails du profil
    Informations personnelles :
    Âge : 50

    Informations forums :
    Inscription : Novembre 2004
    Messages : 386
    Points : 264
    Points
    264
    Par défaut
    Merci Laurent pour ton aide

  9. #9
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    Pour ma part je me serai plus orienté sur de la mise en forme avant conversion.

    Non ?

    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    $file = @'
    Nom1 Nom2 Nom3
    ==============
    Col1 Col2 Col3
    Col1 Col2 Col3
     
     
     
    Nom1 Nom2 Nom3 Nom4
    ===================
    Col1 Col2 Col3 Col4
    Col1 Col2 Col3 Col4
     
    Nom1 Nom2
    =========
    Col1 Col2
    Col1 Col2
    '@
     
    $Arrays = New-Object System.Collections.ArrayList
     
    # Supprime les lignes commencant par =
    $file = $file -replace '(?m)^=.*\r?\n', ''
     
    # Divise par bloc pour chaque double (ou plus) retour ligne
    $datas = $file -split '(?m)(?:\r?\n){2,}'
     
    # Pour chaque bloc
    $datas | ForEach-Object {
        # Convertion en csv
        $csv = ConvertFrom-Csv -InputObject $_ -Delimiter " "
        # Stockage dans Arrays
        $Arrays.Add($csv) | Out-Null
    }

  10. #10
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ericlm128 Voir le message
    Pour ma part je me serai plus orienté sur de la mise en forme avant conversion.
    Oui, c'est une autre approche.
    Mais ici comme on ne connait pas les spécifications détaillés (la liste des différents cas rencontrés) je trouve malaisé de choisir une implémentation, ceci dit la tienne est plus concise et plus lisible.
    Par contre j'ai ceci en résultat d'analyse :
    Code Powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    Nom1 Nom2 Nom3
    ---- ---- ----
    Col1 Col2 Col3
    Col1 Col2 Col3
     
     
     
    Nom1 Nom2 Nom3
    Col1 Col2 Col3
    Col1 Col2 Col3
     
    Nom1 Nom2
    Col1 Col2
    Col1 Col2
    Et il n'y qu'un seul tableau contenant l'intégralité des lignes.

  11. #11
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    Oui ben c'est sur que si tu prend un exemple qui ne marche pas ça ne va pas fonctionner

    Tes lignes vides ne le sont pas puisqu'elle commence par un espace. Il n'y à donc pas deux retours lignes contiguë de trouvé pour la division par bloc.
    On peux ajouter un peu de robustesse avec le code ci-dessous.

    Mon code tout comme le tiens sont du traitement de texte et ne traiterons pas n'importe quoi en entré.
    Il faut un minimum de respect de mise en forme attendue.

    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    $file = @'
     
     
     
    Nom1 Nom2 Nom3
    ---- ---- ----
    Col1 Col2 Col3
    Col1 Col2 Col3
     
     
     
    Nom1 Nom2 Nom3
    =====
    Col1 Col2 Col3
    Col1 Col2 Col3
     
    Nom1 Nom2
    Col1 Col2
    Col1 Col2
    '@
     
    $Arrays = New-Object System.Collections.ArrayList
     
    # Divise par bloc pour chaque double (ou plus) retour ligne
    $datas = $file -split '(?m)(?:\s*\r?\n){2,}'
     
    # Pour chaque bloc
    $datas | ForEach-Object {
        # Supprime les lignes commencant par =, -, caractère d'espacement
        $data = $_ -replace '(?m)^[\s\-=].*\r?\n', ''
     
        # Si les données sont vide, on passe à l'itération suivante
        if ($data -match '(?m)^\s*$')
        {
            return
        }
     
        # Convertion en csv
        $csv = ConvertFrom-Csv -InputObject $data -Delimiter " "
        # Stockage dans Arrays
        $Arrays.Add($csv) | Out-Null
    }

  12. #12
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par ericlm128 Voir le message
    Oui ben c'est sur que si tu prend un exemple qui ne marche pas ça ne va pas fonctionner
    Je suis d'accord
    J'ai juste fait un copier/coller de ton code, de la page dans la console.
    Je ne retrouve pas la colonne 4 dans le résultat, d'où ma remarque:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Nom1 Nom2 Nom3 Nom4
    ===================
    Col1 Col2 Col3 Col4
    Le dernier code fonctionne.

  13. #13
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Au temps pour moi, c'est ce foutu formatage de PS qui se base sur la première structure émis dans le pipe

  14. #14
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    c'est ce foutu formatage de PS qui se base sur la première structure émis dans le pipe
    Je n'ai pas trop comprit le problème mais si finalement ça fonctionne ça me rassure.

  15. #15
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    PS a une règle de formatage lors de l'affichage d'un résultat sur la console
    Code Powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
     $Arrays
     
    # Nom1 Nom2 Nom3
    # ---- ---- ----
    # Col1 Col2 Col3
    # Col1 Col2 Col3
    # Col1 Col2 Col3
    # Col1 Col2 Col3
    # Col1 Col2
    # Col1 Col2
     
    #premier éléments, 3 propriétés PS affiche tous les objets avec 3 mêmes propriétés
    $Arrays[0]
     
    # Nom1 Nom2 Nom3
    # ---- ---- ----
    # Col1 Col2 Col3
    # Col1 Col2 Col3
     
    #Nom 4 n'est pas affiché mais présent sur cet objet
    $Arrays[1]
     
    # Nom1 Nom2 Nom3 Nom4
    # ---- ---- ---- ----
    # Col1 Col2 Col3 Col4
    # Col1 Col2 Col3 Col4
     
    #Nom3 est affiché mais absent des propriétés de cet objet
    $Arrays[2]
     
    # Nom1 Nom2
    # ---- ----
    # Col1 Col2
    # Col1 Col2
    Si on oublie cette règle, on se dit 'le résultat est faux'.

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

Discussions similaires

  1. [AC-2010] Changer le format d'Export d'un fichier txt suite à un programme VBA
    Par dagada75 dans le forum VBA Access
    Réponses: 23
    Dernier message: 17/11/2013, 15h05
  2. remplir tableaux à partir de fichier txt
    Par saedkhella dans le forum Langage
    Réponses: 5
    Dernier message: 14/04/2009, 16h24
  3. format "JMA" colonne d'un fichier TXT
    Par oliver75 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 10/12/2007, 14h43
  4. Mise à jour d'une table avec un fichier csv
    Par blackangel dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 26/05/2005, 14h46
  5. Mise en place d'un serveur de fichier Samba/RedHat
    Par shaun_the_sheep dans le forum Réseau
    Réponses: 2
    Dernier message: 11/01/2005, 08h22

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