Как заменить строку в файле с помощью PowerShell?

Я пытаюсь прочитать замену строки в файле конфигурации с помощью PowerShell. Иногда этот скрипт работает, но большую часть времени он не заменяет строку.

(Get-Content D:\home\App_Config\Sitecore.config) '
    | %{ $_ -replace '  <setting name="Media.MediaLinkServerUrl" value=" "/>',' <setting name="Media.MediaLinkServerUrl" value="https://newurl.com"/>'} '
    | Set-Content D:\home\App_Config\Sitecore.config

Ответ 1

Попробуйте следующее:

$file = 'D:\home\App_Config\Sitecore.config'
$regex = '(?<=<setting name="Media\.MediaLinkServerUrl" value=")[^"]*'
(Get-Content $file) -replace $regex, 'https://newurl.com' | Set-Content $file

* Re Set-Content: по умолчанию используется стандартная однобайтовая кодировка вашей системы, поэтому вы можете использовать -Encoding для -Encoding управления кодировкой выходного файла.
* Также обратите внимание на требуемый (...) вызов Get-Content чтобы убедиться, что конвейер может записать обратно в тот же файл, который прочитал Get-Content.
* Если есть вероятность, что открытый тег, о котором идет речь (<setting...>), охватывает несколько строк, используйте
Get-Content -Raw $file (PSv3+) для чтения всего содержимого файла в виде одной строки (спасибо, deadlydog);
без -Raw, Get-Content возвращает массив строк, представляющий строки ввода.

Из-за использования регулярного выражения в соответствии с существующими настройками любой текст, находящийся внутри value="..." будет соответствовать, поэтому эта команда будет работать даже при повторном запуске.

Напротив, то, что вы пытались, использует эффективный литерал (... value=" "), чтобы найти, что заменить, и после 1-го - успешного запуска, этот литерал больше не совпадает, а последующие прогоны терпят неудачу.

@neha с тех пор заявила, что значение перезагружается вручную перед каждым прогоном, поэтому причина прерывистых сбоев с кодом в вопросе пока неизвестна.Однако представленное здесь решение работает.

В приведенной выше команде используется упрощенный подход к замене:

  • (?<=<setting name="Media.MediaLinkServerUrl" value=") - это утверждение позади ((?<=...)), которое соответствует, но не фиксирует, что оно соответствует: оно находит часть вверх включая и открытие " значения, которое вы пытаетесь заменить, не делая этот префикс частью того, что будет заменено.

  • [^"]* затем соответствует всем значениям, вплоть до закрытия, но не включая закрытие ". ([^"] - это набор символов, который соответствует любому символу, отличному от (^) a ", и * находит любую (возможно, пустую) последовательность таких символов.

  • Поэтому, поскольку в регулярном выражении было записано только само значение, все, что вам нужно указать, поскольку строка замены является новым значением.

Ответ 2

Используйте оператор "Заменить" следующим образом:

$file = 'D:\home\App_Config\Sitecore.config'
$find = '  <setting name="Media.MediaLinkServerUrl" value=" "/>'
$replace = ' <setting name="Media.MediaLinkServerUrl" value="https://newurl.com"/>'

(Get-Content $file).replace($find, $replace) | Set-Content $file