Замените параметр, удаляя пробел, который он не должен - PullRequest
1 голос
/ 31 марта 2019

У меня проблема с пониманием следующего оператора замены.

'Select {0}' -replace '[^\\](\{0\})', 'Success'

Я ожидаю: Выбрать Успех

Вместо этого результат: SelectSuccess

Шаблон '[^\\](\{0\})' можно деконструировать следующим образом:

  • Соответствует одному символу НЕ в списке '\'
  • Сопоставить шаблон внутри и захватить его совпадение
    • Совпадение символа '{' буквально
    • Совпадение символов '0' буквально
    • Совпадение символа '}' буквально

Если я удалю Not section [^\\].затем результат становится снова Выберите Успех

Я что-то упустил?

Ответы [ 3 ]

2 голосов
/ 31 марта 2019

Когда LotPings указывает в комментарии, проблема в том, что [^\\] соответствует пробелу перед {0}, поэтому заменяемое полное совпадение равно {0}, что объясняет, почему результатis SelectSuccess.

Решение состоит в том, чтобы использовать отрицательное косвенное утверждение :

Select {0}' -replace '(?<!\\)\{0\}', 'Success'

(?<!\\) гарантирует, что подвыражение \{0\} не является (!) предшествует ((?<...) a \ char.(\\) без учета этого символа.в матче .

Как указывает LotPings, использование вами группы захвата ((...)) в регулярном выражении не имеет никакого эффекта, поскольку вы не ссылаетесь на нее как на обратную ссылку внутрирегулярное выражение (\1) ни в операнде замены ($1).

Обратите внимание, что -replace всегда заменяет то, что регулярное выражение захватывает в целом , независимо от групп захвата.Чтобы сопоставить части ввода без включения их в захваченный результат, используйте проверочные утверждения , как показано выше.

2 голосов
/ 31 марта 2019

Примечание редактора. В этом ответе показана общая методика форматирования строки, доступная в PowerShell, но ее использование не является вариантом в конкретном случае OP, поскольку требуется условная замена строки.

Знали ли вы operator.of -f. PowerShell имеет возможность форматирования строк, как в .net.

Пример: -

'Select {0}' -f 'Success'

'Select {0} {1}' -f 'All','Files'

Обратитесь к статье ниже, чтобы понять, как это делается в .Net, то же самое можно сделать, используя -f

https://docs.microsoft.com/en-us/dotnet/api/system.string.format?view=netframework-4.7.2#examples

1 голос
/ 02 апреля 2019

Вы хотите сделать две вещи:

  • Найдите {0}, который не начинается с экранированного {, учитывая, что до { может быть \\, обозначающий буквальный обратный слеш (используйте (?<=(?<!\\)(?:\\{2})*)\{0\} регулярное выражение и заменяйте на Success)
  • "Unescape" - все экранированные символы, где экранирующий символ - буквальная обратная косая черта (используйте (?s)\\(.) регулярное выражение и замените на $1)

Используйте

'Select \\\{0}' -replace '(?<=(?<!\\)(?:\\{2})*)\{0\}', 'Success' -replace '(?s)\\(.)', '$1'

Шаблон 1, детали

  • (?<=(?<!\\)(?:\\{2})*) - положительный взгляд, который, непосредственно слева от текущего местоположения, требует
    • (?<!\\) - нет \ разрешено сразу слева от текущего местоположения
    • (?:\\{2})* - 0 или более повторов двойной обратной косой черты
  • \{0\} - строка {0}.

См. Демоверсию regex .

Шаблон 2 детали

  • (?s) - опция RegexOptions.Singleline, которая позволяет . соответствовать символам новой строки
  • \\ - буквальная обратная косая черта
  • (.) - Захват группы 1: любой символ (он будет возвращен в результирующую строку после замены совпадения).

См. это демо регулярных выражений .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...