Как заменить одно вхождение определенного слова в текстовом файле - PullRequest
0 голосов
/ 16 октября 2019

У меня есть файл configuration.txt, который мой скрипт использует для заполнения переменных в моем скрипте. Текстовый файл выглядит следующим образом:

Setting1= Yes
Setting2= Yes
Setting3= Yes

Затем я заполняю свои переменные как таковые (чтобы просто нажать Да или Нет):

$Setting1=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting1='})
$Setting1=($Setting1 -Split '=', 2)[1].trim()

$Setting2=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting2='})
$Setting2=($Setting2 -Split '=', 2)[1].trim()

$Setting3=(Get-Content -Path .\configuration.txt | Where-Object {$_ -match 'Setting3='})
$Setting3=($Setting3 -Split '=', 2)[1].trim()

Тогда у меня есть некоторая логика, и если пользователь,с помощью подсказок в моем скрипте измените эти настройки, скрипт обновит текстовый файл следующим кодом:

((Get-Content -Path .\configuration.txt -Raw | Where-Object {$_ -match 'Setting1'}) -replace $Setting1, $UserSetting1) | Set-Content -Path .\configuration.txt

Где $ UserSetting1 - ввод пользователя («да» или «нет»).

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

Другими словами, если пользователь хочет изменить настройку 1 на «нет» и оставить настройки 2 и 3 как «да»;сценарий меняет все настройки на Да, а не только на настройку 1.

У меня сложилось впечатление, что я должен использовать -Raw для выполнения -relace, но, как указано выше, кажется, чтоФункция -match не работает с функцией -Raw ... и если я не использую -raw, то мой файл конфигурации будет перезаписан только с одной строкой, которую я сопоставил.

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Вы можете просто использовать Оператор замены , чтобы сделать обновление.

$UserSetting1 = 'No'
(Get-Content -Path .\configuration.txt) -replace '(?<=Setting1=).*',$UserSetting1 |
    Set-Content

Поскольку -replace использует механизм сопоставления регулярных выражений, вы можете создать совпадение, чтобы возвращать только данныеВы хотите заменить. Строка замены может быть переменной. Ниже приведено объяснение регулярных выражений. Он соответствует оставшимся символам в строке после Setting1=, а затем заменяет эти символы значением, сохраненным в $UserSetting1. Строки, которые не соответствуют друг другу, будут возвращены без замены.

  • (?<=) - это положительное выражение в виде регулярного выражения. Он утверждает, что в данной позиции строки есть точное совпадение.
  • Setting1= буквальное совпадение строки Setting1=.
  • .* столько символов, скольковозможно до конца строки (непосредственно перед символом новой строки) [1] .

При использовании переключателя -Raw содержимое файла считывается как одна строка. Если вы выполняете совпадение с регулярным выражением (-match) для одной строки, у которой есть совпадение, возвращается $true. Вся строка считается совпадением и по умолчанию захватывает группу 0. $matches[0] содержит это совпадение. Поэтому, если вы используете -replace для замены подстроки в этом совпадении, она заменит каждый экземпляр этой подстроки, которая соответствует -replace критерию соответствия.

Если -RawПереключатель не используется, тогда содержимое файла читается как массив строк. -replace само по себе будет заменять каждый случай совпадения. Однако теперь вы можете использовать -match и Where-Object для выполнения другого кода для определенных совпавших строк.

Объединение -match и -replace без -Raw может привести только к подмножеству прочитанных данных. ,Когда вы обрабатываете каждую строку файла, -match по существу отфильтровывает все строки, которые не возвращают $true до обработки любых замен. Этот сценарий подходит для возврата замены, но может вызвать проблемы, когда вы пытаетесь переписать весь файл. Вам потребуется дополнительная логика для отслеживания того, какие элементы массива у вас есть и которые не были изменены, и выводить их соответствующим образом при обновлении содержимого.


[1] . can соответствовать символам новой строки, если режим регулярных выражений однострочный. Вы можете включить этот режим в регулярном выражении -replace, начав его с (?s).

0 голосов
/ 17 октября 2019

Другой подход заключается в чтении файла конфигурации и сохранении пар имя / значение в Hashtable.

Если порядок, в котором параметры отображаются в текстовом файле, не важен, вы можете использовать ConvertFrom-StringData командлет. Это проанализирует имена и значения настроек и вернет их как Hashtable.

$config = Get-Content -Path .\configuration.txt -Raw | ConvertFrom-StringData

Если порядок DOES имеет значение, создайте упорядоченный хеш (требуется PowerShell 3.0 или выше):

$config  = [ordered]@{}
Get-Content -Path D:\configuration.txt | ForEach-Object {
    $name, $value = ($_ -split '=' , 2).Trim()
    $config[$name] = $value
}

Если пользователь хочет, например, изменить значение Setting1 на no ($ UserSetting1 = 'no'), просто выполните:

$UserSetting1 = 'no'
$config.Setting1 = $UserSetting1

# Next save the updated settings back to the textfile
$newContent = foreach($name in $config.Keys) {
    '{0} = {1}' -f $name, $config.$name
}
$newContent | Set-Content -Path .\configuration.txt -Force
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...