Я делаю замену строки в PowerShell. У меня нет контроля над заменяемыми строками, но я могу воспроизвести возникшую у меня проблему следующим образом:
> 'word' -replace 'word','@#$+'
@#word
Когда фактический результат мне нужен
> 'word' -replace 'word','@#$+'
@#$+
Строка $+
расширяется до заменяемого слова, и я никак не могу найти способ предотвратить это. Я пытался экранировать $
с помощью \
(как если бы это было регулярное выражение), с помощью backtick `
(как и в обычном способе PowerShell). Например:
> 'word' -replace 'word',('@#$+' -replace '\$','`$')
@#`word
Как заменить на литерал $+
в PowerShell? Для чего это стоит, я использую PowerShell Core 6, но это воспроизводимо и в PowerShell 5.
4 ответа
Вместо использования оператора -replace
вы можете использовать метод .Replace()
следующим образом:
PS> 'word'.Replace('word','@#$+')
@#$+
Метод .Replace()
происходит из класса .NET String, тогда как оператор -Replace
реализован с использованием System.Text.RegularExpressions.Regex.Replace()
.
Более подробная информация здесь: https://vexx32.github.io/2019 / 03 / 20 / PowerShell - Заменить - Operator /
-replace
оператор PowerShell:
использует регулярное выражение (регулярное выражение) в качестве поиска (1-й) операнд
- если вы хотите использовать строку поиска дословно , экранируйте ее с помощью
[regex]::Escape()
(в строковых литералах вы можете альтернативно\
- экранировать отдельные символы, которые иначе были бы интерпретированы как метасимволы регулярных выражений).
- если вы хотите использовать строку поиска дословно , экранируйте ее с помощью
использует не-литеральную строку, которая может ссылаться на то, что соответствовало регулярному выражению , как замена (2-й) операнд , через
$
- с префиксами, такими как$&
или$+
(см. ссылку выше или Подстановки в регулярных выражениях).- если вы хотите использовать замещающую строку дословно , double любые
$
символы. (см. ниже).
- если вы хотите использовать замещающую строку дословно , double любые
Если и , ваша строка поиска и ваша строка замены должны использоваться дословно , рассмотрите возможность использования типа [string]
.Replace()
метод вместо этого, как показано в полезном ответе Брэндона Олина.
Предупреждение:
.Replace()
по умолчанию чувствителен к регистру , тогда как-replace
нечувствителен к регистру (как PowerShell вообще есть); используйте другую.Replace()
перегрузку для нечувствительности к регистру или, наоборот, используйте вариант-creplace
в PowerShell для получения чувствительности к регистру.- Case- нечувствительный
.Replace()
пример:
'FOO'.Replace('o', '@', 'CurrentCultureIgnoreCase')
- Case- нечувствительный
.Replace()
быстрее-replace
, хотя это имеет значение только в циклах с большим количеством итераций.
Если в вашем случае вы будете придерживаться оператора -replace
, вы можете использовать метод .Replace()
для требуемого экранирования -replace
замещающего операнда:
# *Doubling* the `$` in the replacement operand ensures that they're used verbatim.
'word' -replace 'word', '@#$+'.Replace('$', '$$')
Вы также можете сделать это с помощью вложенной -replace
операции, но это становится громоздким (\$
экранирует $
в регулярном выражении; $$
представляет собой single $
в строке замены):
# Same as above.
'word' -replace 'word', ('@#$+' -replace '\$', '$$$$')
Другими словами: эквивалент:
'word'.Replace('word','@#$+')
Является:
'word' -creplace [regex]::Escape('word'),'@#$+'.Replace('$', '$$')
Однако, как указано, если и строка поиска, и операнд замены должны использоваться дословно, использование .Replace()
является предпочтительным как для краткости, так и для производительности.
Я не смог найти документально подтвержденное, но правило экранирования в стиле «Visual Basic» сработало, повторяйте символ.
'word' -replace 'word','@#$$+'
дает вам: @#$+
Это сбивает с толку, как эти коды не документированы в «об операторах сравнения». За исключением того, что у меня есть закрытый отчет об ошибках под ними, если вы посмотрите: «Ух, где все эти 2-аргументные коды задокументированы?». https: // docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comparison_operators?view=powershell-7 Это стало моей ссылкой. «$ +» означает «Заменяет последнее захваченное совпадение». Удвоение знака доллара работает, «заменяет один« $ »буквальный»:
'word' -replace 'word','@#$$+'
@#$+
Или используйте версию скрипта второго аргумента в PS 6 и выше (может быть медленнее):
'word' -replace 'word',{'@#$+'}
Похожие вопросы
Связанные вопросы
Новые вопросы
powershell
PowerShell - это кроссплатформенная утилита командной строки и сценариев от Microsoft. Используйте этот тег только для вопросов о написании и выполнении сценариев PowerShell. Вопросы программирования, относящиеся к кроссплатформенной версии PowerShell Core (Windows, macOS и Linux), должны быть помечены [powershell-core]. Вопросы о системном администрировании следует задавать в случае сбоя суперпользователя или сервера.