Excluindo linhas inteiras em um arquivo de texto com base em uma correspondência parcial de seqüência de caracteres com o Windows PowerShell

22

Portanto, tenho vários arquivos de texto grandes que preciso classificar e remover todas as ocorrências de linhas que contêm uma determinada palavra-chave. Então, basicamente, se eu tiver essas linhas:

Isso não é um teste
Isso é um teste
Talvez um teste
Definitivamente não é um teste

E eu executo o script com 'not', preciso excluir totalmente as linhas 1 e 4.

Eu tenho tentado com:

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

mas apenas substitui o 'Programa' e não a linha inteira.

karel
fonte

Respostas:

25

Aqui está o que eu faria:

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

A linha de Snark faz o mesmo, mas começa com o carregamento de todo o arquivo em uma matriz, o que pode ser problemático com arquivos grandes em termos de memória.

buti-oxa
fonte
Sugiro que você use Set-Content em vez de Out-File, o primeiro lida com dados brutos e não corta seqüências de caracteres ou formata objetos.
JasonMArcher
@JasonMArcher Você pode postar um exemplo usando Set-Content? Não acredito que Set-Contentseja um substituto para o drop-in Out-File.
Iain Samuel McLean Elder
Get-Content .\in.txt | Where-Object {$_ -notmatch 'not'} | Set-Content out.txt Out-File é basicamente Set-Content, mas executa a entrada através da formatação padrão em vez da simples conversão de string.
23412 JasonMArcher
Eu tive exatamente o mesmo problema e você responde é 99% do que eu preciso. A questão final é que estou executando o comando em um loop com uma variável $ (substituindo 'not' no seu exemplo). Se eu codificar uma string, ela funcionará perfeitamente; mas se eu usar uma variável, ela não fará nada. Alguma idéia do porquê? Eu tentei tanto a variável nua e colocá-lo em "aspas"
Stephen R
Como isso pode ser modificado para substituir o texto nessas linhas
Tom
7

Isso funcionará:

(Get-Content "D:\Logs\co2.txt") -notmatch "not" | Out-File "D:\Logs\co2.txt"
Snark
fonte
Isso apenas retorna uma única linha no segundo arquivo chamado True.
Correção: Isso retorna uma única linha no segundo arquivo que consiste em 'True'. Talvez esteja faltando o "Foreach-Object {$ _" para que seja executado uma vez por linha? Edit: Bem, na verdade é irrelevante agora, apagou o arquivo que eu esperava limpar. De qualquer forma, obrigado pela ajuda, mas ainda estou curioso para saber qual seria o comando correto para que eu possa fazer isso no futuro?
1
Funciona para mim com suas 4 linhas de teste acima.
Snark
2
nunca substituiria o arquivo original!
usar o seguinte comando
3
concordou, mas usei os mesmos nomes de arquivo usados ​​no pôster original para facilitar a resposta. Ele usou o co2.txt para entrada e saída.
Snark
0

Você também pode usar 'Select-String' com a opção -notmatch:

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

Eu só precisava fazer isso funcionar e vi o seguinte:

$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

A chave é que o 'Where-Object' usando um bloco de script (conforme indicado pelas chaves) requer a declaração da variável em um evento de criação de bloco de script, portanto, o

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

linha.

Ao estruturá-la dessa maneira, é possível criar uma função, passar uma string de texto para corresponder parcialmente, executar a criação do bloco de scripts com o valor passado e fazer com que funcione corretamente.

As respostas acima não explicam corretamente como passar o valor a ser substituído dentro de uma variável.

Walkabout Tigger
fonte
Você pode explicar (mais claramente) como isso é melhor do que a resposta (muito mais concisa) de Snark ? Por favor, não responda nos comentários; edite sua resposta para torná-la mais clara e completa.
22318 Scott