2016-01-12 4 views
1

Я пытаюсь заменить определенную строку в нескольких logonscripts (> 2000 скриптов).заменить содержимое нескольких файлов с помощью PowerShell

Сценарий работает в текущей форме, но записывает каждый файл на диск, даже если никаких изменений не внесено, но я не хочу этого поведения. Он должен записываться на диск только в случае внесения изменений.

Это то, что у меня уже есть:

$varFiles = Get-ChildItem $varPath*.$VarEnding 
foreach ($file in $varFiles) 
{ 
    (Get-Content $file) | 
    Foreach-Object { $_ -replace [regex]::Escape("$varFind"), "$varReplace" } | 
    Set-Content $file 
} 

И это то, что я уже пробовал, но мне кажется, что это не представляется возможным использовать, если в трубопроводных команд:

$varFiles = Get-ChildItem $varPath*.$VarEnding 
foreach ($file in $varFiles) 
{ 
    $control = $file 
    (Get-Content $file) | 
    Foreach-Object { $_ -replace [regex]::Escape("$varFind"), "$varReplace" } | 
    If($control -ne $file){Set-Content $file} 
} 

переменные $ varPath, $ varEnding, $ varFind и $ varReplace определяются несколькими командами Read-Host в начале скрипта.

Я надеюсь, что вы, ребята, можете помочь мне :)

ответ

0

Для простоты и скорости - хотя за счет использования памяти - я бы просто кэшировать и работать на целых входных файлов (требуется PowerShell v3 +, из-за использование -Raw[1]); сценарии входа в систему, так как, как правило, небольшие, то это должно быть приемлемым:

$varFindEscaped = [regex]::Escape($varFind) 
$varReplaceEscaped = $varReplace -replace '\$', '$$$$' 

foreach ($file in Get-ChildItem $varPath*$varEnding) { 
    $contentBefore = Get-Content -Raw $file 
    $contentAfter = $contentBefore -replace $varFindEscaped, $varReplaceEscaped 
    if ($contentBefore -ne $contentAfter) { 
    Set-Content $file $contentAfter 
    } 
} 
  • Для повышения производительности я переехал побега из -regex операндов вне цикла.
    • Обратите внимание, что я также избежать $ экземпляров в значения в замены, чтобы предотвратить их интерпретацию как ссылки на то, что соответствует, например, $& ссылаться на весь матч.
  • Учтите, что Set-Content по умолчанию использует кодовую страницу системы по умолчанию, а не кодировку UTF-8.

[1] В PS v2, вы можете опустить -Raw, который превращает $contentBefore в массив строк (строки) на элементы которого -replace затем работает по отдельности (как в ОП-х подход). Хотя, вероятно, немного медленнее, у него есть преимущество в том, что он выполняет замещение только на отдельных линиях, а не через несколько линий.

+0

Благодарим за предложение, но я использую PS v2, поэтому этот, к сожалению, не работает для меня. У вас есть способ добиться этого в PS v2? –

+0

Я просто удалил атрибут -raw из Get-Content, чтобы использовать его на PS v2, и он работал как шарм на моих 10 тестовых файлах. Большое спасибо! :) –

+0

@ LöwäCent Рад это слышать; Я добавил примечание re '-Raw' к ответу. – mklement0