Usando o PowerShell, desejo substituir todas as ocorrências exatas de [MYID]
um determinado arquivo por MyValue
. Qual é a maneira mais fácil de fazer isso?
powershell
amador
fonte
fonte
Respostas:
Use (versão V3):
Ou para V2:
fonte
Observe que os parênteses
(Get-Content file.txt)
são necessários:fonte
Set-Content
vez de você,Out-File
você recebe um aviso como "O processo não pode acessar o arquivo '123.csv' porque está sendo usado por outro processo." .Get-Content
parênteses, funciona. Você pode explicar em sua resposta por que o parêntese é necessário? Eu ainda substituiriaOut-File
porSet-Content
porque é mais seguro; ele protege você de eliminar o arquivo de destino se você esquecer os parênteses.Set-Content
vez deOut-File
é uma solução muito melhor e mais segura. Desculpe ter que votar.Prefiro usar a classe File do .NET e seus métodos estáticos, como visto no exemplo a seguir.
Isso tem a vantagem de trabalhar com uma única String em vez de uma string-array como no Get-Content . Os métodos também cuidam da codificação do arquivo (UTF-8 BOM , etc.) sem que você precise cuidar da maior parte do tempo.
Além disso, os métodos não atrapalham as terminações de linha (finais de linha Unix que podem ser usadas) em contraste com um algoritmo usando Get-Content e passando para Set-Content .
Então, para mim: menos coisas que poderiam quebrar ao longo dos anos.
Uma coisa pouco conhecida ao usar classes .NET é que, quando você digita "[System.IO.File] ::" na janela do PowerShell, pode pressionar a Tabtecla para percorrer os métodos existentes.
fonte
[System.IO.File] | gm
C:\Windows\System32\WindowsPowerShell\v1.0
?O exemplo acima é executado apenas para "Um arquivo", mas você também pode executá-lo para vários arquivos na sua pasta:
fonte
foreach
você pode fazer isso #Get-ChildItem 'C:\folder\file*.xml' -Recurse | ForEach { (Get-Content $_).Replace('[MYID]', 'MyValue') | Set-Content $_ }
foreach
, porque Get-Content faz algo que você não pode esperar ... Ele retorna uma matriz de seqüências de caracteres, onde cada sequência é uma linha do arquivo. Se você estiver percorrendo um diretório (e subdiretórios) que estão em um local diferente do seu script em execução, você desejará algo assim:Get-ChildItem $Directory -File -Recurse | ForEach { (Get-Content $_.FullName) | ForEach { $_ -replace '[MYID]', 'MyValue' } | Set-Content $_.FullName }
onde$Directory
está o diretório que contém os arquivos que você deseja modificar.Você pode tentar algo como isto:
fonte
É isso que eu uso, mas é lento em arquivos de texto grandes.
Se você vai substituir cadeias de caracteres em arquivos de texto grandes e a velocidade é uma preocupação, consulte o System.IO.StreamReader e System.IO.StreamWriter .
(O código acima não foi testado.)
Provavelmente, existe uma maneira mais elegante de usar o StreamReader e o StreamWriter para substituir o texto em um documento, mas isso deve oferecer um bom ponto de partida.
fonte
Eu achei uma maneira um pouco conhecida, mas incrivelmente legal de fazê-lo no Windows Powershell em Ação de Payette . Você pode fazer referência a arquivos como variáveis, semelhantes a $ env: path, mas precisa adicionar chaves.
fonte
$myFile
?$a = 'file.txt'; invoke-expression "`${c:$a} = `${c:$a} -replace 'oldvalue','newvalue'"
Se você precisar substituir seqüências de caracteres em vários arquivos:
Deve-se observar que os diferentes métodos publicados aqui podem ser muito diferentes em relação ao tempo que leva para ser concluído. Para mim, eu regularmente tenho um grande número de arquivos pequenos. Para testar o melhor desempenho, extraí 5,52 GB (5.933.604.999 bytes) de XML em 40.693 arquivos separados e executei três das respostas que encontrei aqui:
fonte
Crédito para @ rominator007
Eu o envolvi em uma função (porque você pode usá-lo novamente)
NOTA: Isto NÃO diferencia maiúsculas de minúsculas !!!!!
Consulte esta publicação: String.Replace ignoring case
fonte
Isso funcionou para mim usando o diretório de trabalho atual no PowerShell. Você precisa usar a
FullName
propriedade ou ela não funcionará no PowerShell versão 5. Eu precisava alterar a versão do .NET framework de destino em TODOS os meusCSPROJ
arquivos.fonte
Um pouco velho e diferente, pois eu precisava alterar uma determinada linha em todas as instâncias de um nome de arquivo específico.
Além disso,
Set-Content
não estava retornando resultados consistentes, então tive que recorrer aOut-File
.Código abaixo:
Foi o que funcionou melhor para mim nesta versão do PowerShell:
fonte
Correção pequena para o comando Set-Content. Se a string pesquisada não for encontrada, o
Set-Content
comando deixará em branco (vazio) o arquivo de destino.Você pode primeiro verificar se a string que você está procurando existe ou não. Caso contrário, não substituirá nada.
fonte
set-content test.txt "hello hello world hello world hello"
e então(get-content .\test.txt).Replace("something", "awesome") | set-content .\test.txt
não esvaziará o arquivo como sugerido neste.