2008-12-04 8 views
0

J'ai un petit utilitaire qui fait une recherche d'un certain nombre de fichiers. J'ai dû le créer parce que les deux recherches de bureau Windows de Google ne trouvaient pas les lignes appropriées dans les fichiers. La recherche fonctionne bien (je suis prêt à l'améliorer), mais l'une des choses que je voudrais ajouter à mon util est une recherche/remplacement par lots.Lire et mettre à jour le flux de fichiers

Alors, comment serait la meilleure façon de lire une ligne à partir d'un fichier, le comparer à un terme de recherche et si elle passe, puis mettre à jour la ligne, et continuer à travers le reste du fichier?

Répondre

2

je ferais ce qui suit pour chaque fichier:

  • Est-ce que la recherche comme normale. Vérifiez également le jeton à remplacer. Dès que vous l'avez vu, recommencez ce fichier. Si vous ne voyez pas le jeton à remplacer, vous avez terminé.
  • Lorsque vous recommencez, créez un nouveau fichier et copiez chaque ligne que vous avez lue dans le fichier d'entrée, en effectuant le remplacement au fur et à mesure.
  • Lorsque vous avez terminé avec le fichier:
    • Déplacer le fichier en cours à un nom de fichier de sauvegarde
    • Déplacez le nouveau fichier au nom du fichier d'origine
    • Supprimer le fichier de sauvegarde

Faites attention à ne pas faire cela sur des fichiers binaires, par exemple - les conséquences d'une recherche textuelle et d'un remplacement sur des fichiers binaires seraient généralement désastreuses!

+0

Il y a un compromis. Si vous savez que les fichiers auront probablement le SearchTerm, il peut être préférable de démarrer un fichier temporaire en copiant le contenu de l'autre fichier au fur et à mesure. Au lieu de chercher deux fois dans le fichier. – grepsedawk

+0

Oui, je me demandais à ce sujet. Je me suis dit que je donnerais juste l'algorithme simple à la place :) –

0

Si PowerShell est une option, la fonction définie ci-dessous peut être utilisée pour rechercher et remplacer des fichiers. , Vous feriez par exemple, pour trouver 'a string' dans des fichiers texte dans le répertoire courant:

dir *.txt | FindReplace 'a string' 

Pour remettre en place 'a string' avec une autre valeur, il suffit d'ajouter la nouvelle valeur à la fin:

dir *.txt | FindReplace 'a string' 'replacement string' 

Vous pouvez également l'appeler sur un seul fichier en utilisant FindReplace -path MyFile.txt 'a string'.

function FindReplace([string]$search, [string]$replace, [string[]]$path) { 
    # Include paths from pipeline input. 
    $path += @($input) 

    # Find all matches in the specified files. 
    $matches = Select-String -path $path -pattern $search -simpleMatch 

    # If replacement value was given, perform replacements. 
    if($replace) { 
    # Group matches by file path. 
    $matches | group -property Path | % { 
     $content = Get-Content $_.Name 

     # Replace all matching lines in current file. 
     foreach($match in $_.Group) { 
     $index = $match.LineNumber - 1 
     $line = $content[$index] 
     $updatedLine = $line -replace $search,$replace 
     $content[$index] = $updatedLine 

     # Update match with new line value. 
     $match | Add-Member NoteProperty UpdatedLine $updatedLine 
     } 

     # Update file content. 
     Set-Content $_.Name $content 
    } 
    } 

    # Return matches. 
    $matches 
} 

Notez que Select-String prend également en charge les matchs regex, mais a été constrainted à des matchs simples pour la simplicité;) Vous pouvez également effectuer un remplacement plus robuste comme Jon suggéré, plutôt que d'écraser le fichier avec le nouveau contenu.

Questions connexes