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 :

Lire un fichier 1 ligne par ligne et la chercher dans un fichier 2 après modif


Sujet :

Scripts/Batch

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Novembre 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 34
    Par défaut Lire un fichier 1 ligne par ligne et la chercher dans un fichier 2 après modif
    Bonjour,
    Étant un bleu en powershell je solicite votre aide.
    J'ai un fichier que je doit lire ligne par ligne et vérifier si un morceau de cette ligne (après modification) existe dans un autre fichier.
    Si la ligne n'existe pas j'enregistre la ligne d'origine du fichier 1 dans un fichier resultat.txt.

    Exemple 1:
    exemple de données du fichier1:
    F:\users\tom\samba\lina\lina\chapI.log

    Ce qui doit être recherché dans le fichier 2:
    abdallah/samba/lina/lina/chapI.log

    Donc si il faut que je cherche la chaine "tom\samba\lina\lina\chapI.log" en remplaçant tous les \ par des /.

    Exemple 2:
    Si il n'y a pas \samba\ dans une ligne du fichier 1 on doit quand même chercher la chaine avec le \samba\ après le prénom dans le fichier 2
    Fichier 1 F:\users\tim\data\perso\lina carine 014.JPG
    fichier 2: tim/samba/data/perso/lina carine 014.JPG

    J'ai donc cherché a lire le fichier 1 et a stocker sont contenu dans une variable tout en remplaçant les \ par des /
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $contenu_fic1 = Get-Content d:\export\export_fic1.txt | foreach { $_ -replace '[\]',"" }
    Mais je n'arrive pas àlui faire comprendre que le \ et / ne font partie de la commande.

    Ensuite je n'arrive pas à supprimer le "F:\users\" devant chaque ligne du fichier 1 afin de pouvoir rechercher directement la chaine dans le fichier (après avoir inversé les slash).
    J'ai essayé avec la fonction "split", mais je n’arrive pas lui dire de garder tout ce qui est après le 2eme "\" jusqu'à la fin de la ligne. En plus je ne suis pas sur que ce soit la manière la plus simple pour reconstituer la ligne complète...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Get-Content d:\export\export_fic1.txt | foreach { $_.split("\")[3] }
    Merci pour votre aide!

  2. #2
    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
    Billets dans le blog
    1
    Par défaut
    Salut,
    je ne suis pas certains d'avoir compris ton exemple 2.

    Voici une tentative :
    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
     
    Function ConvertTo-SambaPath {
     param ([string] $InputObject)
     
      Write-debug "OldLine:$InputObject"
      $NewLine=$InputObject.Replace('\','/') -replace '^(.:/.*?)/(.*)$','$2'
      Write-debug "NewLine:$NewLine"
      Write-Output $NewLine
    }#ConvertTo-SambaPath
     
    $Line='F:\users\tom\samba\lina\lina\chapI.log'
    $NewLine=ConvertTo-SambaPath $Line
    $NewLine
    #tom/samba/lina/lina/chapI.log
     
    $Ref='tom/samba/lina/lina/chapI.log'
    $NewLine -eq $Ref
     
     
    Function Compare-SambaPath {
     param (
      [string] $InputObject,
      [string] $ReferencePath
     )
      $NewLine=ConvertTo-SambaPath $InputObject
      if ($NewLine.Split('/',[StringSplitOptions]::RemoveEmptyEntries)[1] -ne 'samba')
      { 
         $Newline=$NewLine -replace '^(.*?)/(.*?)/(.*)$','$1/samba/$2/$3'
         Write-debug "Replace NewLine:$NewLine"
      }
      $NewLine -eq $ReferencePath
     
    }#Compare-SambaPath
     
    $Line2='F:\users\tim\data\perso\lina carine 014.JPG'
    $Ref='tim/samba/data/perso/lina carine 014.JPG'
     
    $DebugPreference='Continue'
    if (Compare-SambaPath $Line2 $Ref )
    {"Match"}
    else 
    {"not Match"}
     
    $DebugPreference='SilentlyContinue'

  3. #3
    Membre averti
    Inscrit en
    Novembre 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 34
    Par défaut
    Merci bien,
    Je vais essayer de comprendre le fonctionnement et tester ça!

    Pour l'exemple 2 je vais essayer d'être plus clair
    Si dans le fichier 1 j'ai une ligne: "F:\users\tim\data\perso\lina carine 014.JPG"
    je veux "simplement" chercher dans le fichier 2 la chaine ".
    tim\samba\data\perso\lina carine 014.JPG
    En gros qu'il y ai ou pas \samba\ après le prénom ou pas dans le fichier 1 il faut chercher dans le fichier 2 avec \samba\ après le prénom.

    Par contre, chose que j'ai oublié de dire, c'est que dans le fichier 2 il peut y avoir n'importe quoi avant le prénom: "tim/samba/data/perso/lina carine 014.JPG"

  4. #4
    Membre averti
    Inscrit en
    Novembre 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 34
    Par défaut
    Bon, en relisant je pense que je n'ai pas été assez clair dans l'exposition de mont problème:
    J'ai deux fichiers "export_cluster" et "export_samba" contenant chacun des liens vers des fichiers situés dans des home-dir d'utilisateurs de leur OS respectif.

    Le fichier "export_cluster.txt" contient donc le style de ligne suivantes:
    F:\users\tim\samba\Sauvegarde du 15 mai 2007\Courrier\Thunderbird\Profiles\7j71nb1u.default\Mail\pop.inrets.fr\Trash
    F:\users\tom\W7\Backup Set 2012-05-25 121729\Backup Files 2012-05-25 121729\Catalogs\Backup files 31.wbverify
    ...

    Le fichier "export_samba.txt" contient donc le style de ligne suivantes:
    /users/dg/tim/samba/Sauvegarde du 15 mai 2007/Courrier/Thunderbird/Profiles/7j71nb1u.default/Mail/pop.inrets.fr/Trash
    /users/labo1/tom/samba/W7/Backup Set 2012-05-25 121729/Backup Files 2012-05-25 121729/Catalogs/Backup files 31.wbverify
    ...

    Donc:
    Dans le cas du premier chemin nous avons "F:\users\tim\samba\Sauvegarde du 15 mai 2007\Courrier\Thunderbird\Profiles\7j71nb1u.default\Mail\pop.inrets.fr\Trash" donc la recherche à faire dans le fichier "export_samba.txt" est "tim/samba/Sauvegarde du 15 mai 2007/Courrier/Thunderbird/Profiles/7j71nb1u.default/Mail/pop.inrets.fr/Trash"

    Dans le cas du deuxième chemin nous avons "F:\users\tom\W7\Backup Set 2012-05-25 121729\Backup Files 2012-05-25 121729\Catalogs\Backup files 31.wbverify" donc la recherche à faire dans le fichier "export_samba.txt" est "tom/samba/W7/Backup Set 2012-05-25 121729/Backup Files 2012-05-25 121729/Catalogs/Backup files 31.wbverify"

    Il faut donc:
    1) que je lise une par une les ligne du fichier "export_cluster.txt".
    2) je remplace les \ par des / et qu je supprime "F:\users\" de mes ligne à rechercher dans le fichier "export_samba.txt".
    Si dans le fichier "export_cluster.txt", \samba\ n'apparait pas après le nom d'un utilisateur, il faut le rajouter dans la chaine à rechercher (voir 2eme cas).
    3) une fois ma ligne reformaté, je recherche dans le fichier "export_samba.txt" si il contient une corespondance.
    Si oui alors on passe à la ligne suivante du fichier "export_cluster.txt", si non alors on log la ligne d'origine de la recherche "F:\users\......" dans un ficher resultat.txt

    J'espère que c'est plus clair.

    J'ai repris de code de laurent et j'ai commencé à l'adapter pour essayer de coller a ce que je veux mais ça ne fonctionne pas encore comme il faut:
    Code : 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
    Function ConvertTo-SambaPath {
     param ([string] $InputObject)
     
      Write-debug "OldLine:$InputObject"
      $NewLine3=$InputObject.Replace('\','/') -replace '^(.:/.*?)/(.*)$','$2'
      Write-debug "NewLine:$NewLine3"
      Write-Output $NewLine3
    }#ConvertTo-SambaPath
     
    Function Compare-SambaPath {
     param (
      [string] $InputObject,
      [string] $ReferencePath
     )
      $NewLine=ConvertTo-SambaPath $InputObject
      if ($NewLine.Split('/',[StringSplitOptions]::RemoveEmptyEntries)[1] -ne 'samba')
      { 
         $Newline=$NewLine -replace '^(.*?)/(.*?)/(.*)$','$1/samba/$2/$3'
         Write-debug "Replace NewLine:$NewLine"
      }
    }#Compare-SambaPath
     
    $contenu_cluster = Get-Content d:\export\export_cluster.txt
    $contenu_larissa = Get-Content d:\export\export_larissa.txt
    
    foreach ($InputObject in $contenu_cluster) {
        foreach ($ReferencePath in $contenu_larissa) {
            $DebugPreference='Continue'
            Write-Output " "
            Write-Output "*******************"
            if (Compare-SambaPath $NewLine2 $ReferencePath )
            {"Match"
            ADD-content -path d:\export\recuperer.txt -value $InputObject
            }
            else 
            {"not Match"}
            Write-Output "coparaison en cours: "$ReferencePath
            Write-Output "*******************"
            $DebugPreference='SilentlyContinue'
        }
    }
    Le problème c'est que les 2 fichiers "export_cluster.txt" et "export_samba.txt" font respectivement 4Mo et 8.7 Mo. donc avec ce code, le nombre de lignes à tester est énorme, donc c'est très très long!
    Du coup, est-ce que cela fonctionnerai et ne serait pas plus rapide en utilisant une commande du type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    get-content $contenu_larissa | where {$_ -like $NewLine2}
    et donc si vrai alors on enregistre la ligne dans "recuperer.txt"

  5. #5
    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
    Billets dans le blog
    1
    Par défaut
    Valide déjà les regex avec un jeux de tests.
    Essaie ceci :
    Code powershell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    $SambaFile='c:\temp\export_samba.txt'
    $ClusterFile='c:\temp\export_cluster.txt'
     
    $Clusters = @(Get-Content $ClusterFile)
    foreach ($Line  in Get-Content $SambaFile) {
      $Line=$Line.Trim()
      foreach ($Pattern in $Clusters) {
        $Pattern=$Pattern.Trim()  
        if (Compare-SambaPath $Line $Pattern )
        {"Match : $Line";break}
      }
    }
    Autre point à vérifier : la présence d'espace en début et/ou en fin de chaîne est-elle autorisée ?

    Ensuite une autre approche, on regroupe les 2 traitements, on transforme la 1er liste et on utilise compare objet:
    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
    Function ConvertTo-SambaPath {
     param (
        [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
       [string] $InputObject
     )
     
      process { 
        Write-debug "OldLine:$InputObject"
        $NewLine=$InputObject.Replace('\','/') -replace '^(.:/.*?)/(.*)$','$2'
        Write-debug "NewLine:$NewLine"
        if ($NewLine.Split('/',[StringSplitOptions]::RemoveEmptyEntries)[1] -ne 'samba')
        { 
           $Newline=$NewLine -replace '^(.*?)/(.*?)/(.*)$','$1/samba/$2/$3'
           Write-debug "Replace NewLine:$NewLine"
        }
        Write-Output $NewLine
      }
    }# ConvertTo-SambaPath
     
    $T=@(Get-Content $SambaFile|ConvertTo-SambaPath)
    Compare-Object $Clusters $T
    Reste à regrouper (Group-Object) sur la propriété 'SideIndicator'.

    Je le laisse optimiser la V2

  6. #6
    Membre averti
    Inscrit en
    Novembre 2010
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Novembre 2010
    Messages : 34
    Par défaut
    J'ai testé la conversion avec les regex sur plusieurs ligne du fichier "export_cluster et ça fonctionne bien".
    Par contre j'ai plus de mal à réutiliser le code que tu m'a donné...
    Code : 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
    Function Compare-SambaPath {
     param (
      [string] $arg1,
      [string] $arg2
     )
        ConvertTo-SambaPath $arg1 $arg2
    #  if ($NewClusterLine.Split('/',[StringSplitOptions]::RemoveEmptyEntries)[1] -ne 'samba')
    #  { 
    #     $NewClusterLine=$NewClusterLine -replace '^(.*?)/(.*?)/(.*)$','$1/samba/$2/$3'
    #     Write-debug "Replace NewClusterLine:$NewClusterLine"
    #  }
    }#Compare-SambaPath
    
       
    $SambaFile='d:\export\export_samba.txt'
    $ClusterFile='d:\export\export_cluster.txt'
    $result='d:\export\recuperer.txt'
    New-Item -path "d:\export\" -Name recuperer.txt -ItemType file -force
     
    foreach ($ClusterLine in Get-Content $ClusterFile) {
    #retire les espaces en debut et fin de lignes
      $ClusterLine=$ClusterLine.Trim()
        foreach ($SambaLine in Get-Content $SambaFile) {
            $DebugPreference='Continue'
            $SambaLine=$SambaLine.Trim()
            write-output " "
            Compare-SambaPath $ClusterLine $SambaLine
            if ($SambaLine -Like "*$NewClusterLine") {
                write-host "Match"
            }
            Else {
            write-host "Not Match: ajout du chemin $ClusterLine au fichier recuperer.txt "
            add-Content "$result" "$ClusterLine"
            }
        }
    }
    Voici un exemple de resultat qu'il me sort:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DÉBOGUER*: OldLine:F:\users\tim\28_11_05\Nouveau Texte seulement.txt
    DÉBOGUER*: NewLine:tim/28_11_05/Nouveau Texte seulement.txt
    DÉBOGUER*: SambaLine: /users/lab1/toto/.mozilla/firefox/.migrated
    Match
    J'ai donc un problème pour lui faire tester
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($SambaLine -Like "*$NewClusterLine")
    J'arrive pas à trouver la bonne syntaxe.
    Sinon vu le nombre de lignes dans mes fichiers, j'ai seulement à parcourir environ 2 400 000 000 la boucle du script....

Discussions similaires

  1. [AC-2003] lire une table Access en VBA ligne par ligne
    Par afifaNancy dans le forum VBA Access
    Réponses: 6
    Dernier message: 25/06/2012, 13h54
  2. Lire un fichier ligne par ligne avec Awk
    Par Krispy dans le forum Linux
    Réponses: 8
    Dernier message: 07/09/2006, 15h14
  3. Lire un fichier ligne par ligne
    Par Guillaume602 dans le forum C
    Réponses: 3
    Dernier message: 18/03/2006, 21h41
  4. lire un fichier ligne par ligne
    Par peuf23 dans le forum C
    Réponses: 6
    Dernier message: 21/09/2005, 10h43

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