Löschen ganzer Zeilen in einer Textdatei basierend auf einer Teilzeichenfolge, die mit Windows PowerShell übereinstimmt


22

Ich habe also mehrere große Textdateien, die ich sortieren und alle Vorkommen von Zeilen entfernen muss, die ein bestimmtes Schlüsselwort enthalten. Also im Grunde, wenn ich diese Zeilen habe:

Dies ist kein Test
Dies ist ein Test
Vielleicht ein Test Auf
jeden Fall kein Test

Und ich starte das Skript mit 'nicht', ich muss die Zeilen 1 und 4 komplett löschen.

Ich habe versucht mit:

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

Es ersetzt jedoch nur das 'Programm' und nicht die gesamte Zeile.

Antworten:


25

Folgendes würde ich tun:

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

Die Linie von Snark macht dasselbe, aber sie beginnt mit dem Laden der gesamten Datei in ein Array, was bei großen Dateien in Bezug auf den Speicher problematisch sein kann.


Ich würde vorschlagen, dass Sie Set-Content anstelle von Out-File verwenden, das frühere befasst sich mit Rohdaten und schneidet keine Zeichenfolgen ab oder formatiert Objekte.
Jason Mrcher

@JasonMArcher Kannst du ein Beispiel mit posten Set-Content? Ich glaube nicht, dass dies Set-Contentein Ersatz ist Out-File.
Iain Samuel McLean Elder

Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt Out-File ist im Grunde genommen Set-Content, führt die Eingabe jedoch über die Standardformatierung aus, anstatt über eine einfache Zeichenfolgenkonvertierung.
Jason März

Ich hatte genau das gleiche Problem und Sie antworten zu 99% auf das, was ich brauche. Das letzte Problem ist, dass ich den Befehl in einer Schleife mit einer $ -Variablen ausführe (in Ihrem Beispiel 'not' ersetzen). Wenn ich einen String hart codiere, funktioniert er perfekt. aber wenn ich eine Variable benutze, macht es nichts. Irgendeine Idee warum? Ich habe sowohl die nackte Variable ausprobiert als auch in "Anführungszeichen" gesetzt
Stephen R

Wie kann dies geändert werden, um den Text in diesen Zeilen zu ersetzen
Tom

7

Das wird funktionieren:

(Get-Content "D:\Logs\co2.txt") -notmatch "not" | Out-File "D:\Logs\co2.txt"

Dies gibt nur eine einzelne Zeile in der zweiten Datei mit dem Namen True zurück.

Korrektur: Dies gibt nur eine einzelne Zeile in der zweiten Datei zurück, die aus 'True' besteht. Fehlt möglicherweise das "Foreach-Object {$ _", sodass es einmal pro Zeile ausgeführt wird? Bearbeiten: Nun, eigentlich ist es jetzt irrelevant, es löschte die Datei, die ich aufräumen wollte. Trotzdem vielen Dank für die Hilfe, aber ich bin immer noch gespannt, was der richtige Befehl wäre, damit ich dies in Zukunft tun kann.

1
Das funktioniert bei mir mit deinen 4 Testzeilen oben.
Snark

2
hätte es nie geschafft die original datei zu überschreiben!
user33788

3
stimmte zu, aber ich verwendete die gleichen Dateinamen wie auf dem Originalposter, um die Antwort zu erleichtern. Er verwendete co2.txt sowohl für die Eingabe als auch für die Ausgabe.
Snark

0

Sie können auch 'Select-String' mit der Option -notmatch verwenden:

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

0

Ich brauchte nur, um dies zum Laufen zu bringen und kam mit den folgenden:

$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

Der Schlüssel ist, dass das 'Where-Object', das einen Skriptblock verwendet (wie durch die geschweiften Klammern angegeben), die Deklaration der Variablen in einem Skriptblockerstellungsereignis erfordert, daher das

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

Linie.

Durch diese Strukturierung kann eine Funktion erstellt, eine teilweise passende Textzeichenfolge übergeben, die Skriptblockerstellung mit dem übergebenen Wert durchgeführt und ordnungsgemäß ausgeführt werden.

Die obigen Antworten erklären nicht korrekt, wie der zu ersetzende Wert in einer Variablen übergeben wird.


Können Sie (klarer) erklären, wie dies besser ist als die (viel prägnantere) Antwort von Snark ? Bitte antworten Sie nicht in Kommentaren; Bearbeiten Sie Ihre Antwort, um sie klarer und vollständiger zu gestalten.
Scott
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.