Suppression de lignes entières dans un fichier texte basé sur une correspondance de chaîne partielle avec Windows PowerShell

22

J'ai donc plusieurs gros fichiers texte que je dois trier et supprimer toutes les occurrences de lignes qui contiennent un mot-clé donné. Donc, fondamentalement, si j'ai ces lignes:

Ce n'est pas un test
C'est un test
Peut-être un test
Certainement pas un test

Et je lance le script avec «non», je dois supprimer entièrement les lignes 1 et 4.

J'ai essayé avec:

PS C:\Users\Admin> (Get-Content "D:\Logs\co2.txt") | 
Foreach-Object {$_ -replace "3*Program*", ""} | 
Set-Content "D:\Logs\co2.txt"

mais il ne remplace que le «programme» et non la ligne entière.

Karel
la source

Réponses:

25

Voici ce que je ferais:

Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt

La ligne de Snark fait de même, mais elle commence par charger tout le fichier dans un tableau, ce qui peut être problématique avec les gros fichiers en termes de mémoire.

buti-oxa
la source
Je suggérerais que vous utilisiez Set-Content au lieu de Out-File, les premiers traitent des données brutes et ne coupent pas les chaînes ou les objets de format.
JasonMArcher
@JasonMArcher Pouvez-vous publier un exemple en utilisant Set-Content? Je ne pense pas que ce Set-Contentsoit un remplacement sans rendez-vous Out-File.
Iain Samuel McLean Elder
Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt Out-File est essentiellement Set-Content, mais il exécute l'entrée via le formatage par défaut au lieu d'une simple conversion de chaîne.
JasonMArcher
J'ai eu exactement le même problème et vous répondez à 99% de ce dont j'ai besoin. Le dernier problème est que j'exécute la commande en boucle avec une variable $ (en remplaçant 'not' dans votre exemple). Si je code en dur une chaîne, cela fonctionne parfaitement; mais si j'utilise une variable, elle ne fait rien. Une idée pourquoi? J'ai essayé à la fois la variable nue et la mettre entre "guillemets"
Stephen R
Comment cela peut-il être modifié pour remplacer le texte sur ces lignes
Tom
7

Cela fonctionnera:

(Get-Content "D:\Logs\co2.txt") -notmatch "not" | Out-File "D:\Logs\co2.txt"
Snark
la source
Cela renvoie simplement une seule ligne dans le deuxième fichier nommé True.
Correction: Cela ne renvoie qu'une seule ligne dans le deuxième fichier composé de "True". Est-ce qu'il manque peut-être le "Foreach-Object {$ _" pour qu'il s'exécute une fois par ligne? Edit: Eh bien, en fait, cela n'a plus d'importance maintenant, cela a effacé le fichier que j'espérais effacer. Merci pour l'aide de toute façon, mais je suis toujours curieux de savoir quelle serait la commande correcte pour que je puisse faire cela à l'avenir?
1
Cela fonctionne pour moi avec vos 4 lignes de test ci-dessus.
Snark
2
n'aurait jamais écraser le fichier d'origine!
user33788
3
d'accord, mais j'ai utilisé les mêmes noms de fichiers que ceux utilisés par l'affiche originale, pour faciliter la réponse. Il a utilisé co2.txt pour les entrées et les sorties.
Snark
0

Vous pouvez également utiliser 'Select-String' avec l'option -notmatch:

Select-String 'not' .\input.txt -notmatch | % {$_.Line} | set-content output.txt
EZ Hart
la source
0

J'avais juste besoin de faire fonctionner cela et j'ai trouvé ce qui suit:

$InServerName = 'SomeServerNameorIPAddress'
$InFilePath = '\Sharename\SomePath\'
$InFileName = 'Filename.ext'

$OutServerName = 'SomeServerNameorIPAddress'
$OutFilePath = '\Sharename\SomePath\'
$OutFileName = 'Filename.out'

$InFile = -join('\\',$InServerName,$InFilePath,$InFilename)
$OutFile = -join('\\',$OutServerName,$OutFilePath,$OutFilename)
$FindStr = 'some string to match on'
$CompareStr = [scriptblock]::Create($FindStr)
$CompareStr
Get-Content $InFile | Where-Object {$_ -notmatch $CompareStr} | Set-Content $OutFile
Get-Content $OutFile

L'essentiel étant que le "Where-Object" utilisant un bloc de script (comme indiqué par les accolades) nécessite de déclarer la variable dans un événement de création de bloc de script, d'où la

$CompareStr = [scriptblock]::Create($FindStr)

ligne.

En le structurant de cette manière, on peut créer une fonction, lui passer une chaîne de texte pour qu'elle corresponde partiellement, effectuer la création du bloc de script avec la valeur transmise et la faire fonctionner correctement.

Les réponses ci-dessus n'expliquent pas correctement comment passer la valeur à remplacer dans une variable.

Walkabout Tigger
la source
Pouvez-vous expliquer (plus clairement) en quoi cela est meilleur que la réponse de Snark (beaucoup plus concise) ? Veuillez ne pas répondre dans les commentaires; modifiez votre réponse pour la rendre plus claire et plus complète.
Scott