Powershell -replace дает странное поведение
Это сводит меня с ума! Буду признателен за любые указатели на то, что происходит, пожалуйста!
$alpha = 'aaa.bbb.$connection.ccc.ddd'
$s = [regex]::match($alpha,"\$.+?(?=\.)").Value "Alpha is: $alpha"
"Matched chunk is: $s" $newChunk = "'" + $s + "'" "New chunk is: $newChunk"
$beta = $alpha -replace $s,$newChunk
"Beta is: $beta"
Это дает следующий результат:
Alpha is: aaa.bbb.$connection.ccc.ddd
Matched chunk is: $connection New chunk is: '$connection'
Beta is: aaa.bbb.$connection.ccc.ddd
Я пытаюсь идентифицировать / сопоставлять последовательности символов в пути, которые начинаются с буквального символа '$' и продолжаются до тех пор, пока буквальная точка "не включается". char. В приведенном выше примере кода строка будет «$ connection».
Затем мне нужно заключить эту строку в одинарные кавычки, поэтому в приведенном выше примере значение $ newChunk станет «$ connection», включая одинарные кавычки.
Затем мне нужно заменить совпадающее значение новым значением в одиночных кавычках в исходной строке. Независимо от того, что я пробую (то же самое и с методом [regex] :: match), одинарные кавычки удаляются. Итак, по сути, я пытаюсь превратить:
aaa.bbb.$connection.ccc.ddd
в
aaa.bbb.'$connection'.ccc.ddd
Используя Powershell 7.1, я был бы очень признателен, если бы кто-нибудь сказал мне, почему это не работает. Спасибо!
Ответы
Использовать
$beta = $alpha -replace '\$[^.]+', "'$&'"
Смотрите доказательство .
Объяснение
--------------------------------------------------------------------------------
\$ '$'
--------------------------------------------------------------------------------
[^.]+ any character except: '.' (1 or more times
(matching the most amount possible))
Это $&заполнитель для всего совпадения.
Полезный ответ Рышарда Чеха, безусловно, является лучшим решением : в целом ссылка на то, что оператор на основе регулярного выражения -replace сопоставил в своем замещающем операнде с заполнителем,$& является самым простым и надежным решением.
См. Этот ответ, чтобы узнать о других заполнителях, которые вы можете использовать, например о том, что предшествовало ( $`) или успешно ( $') совпадению, или о том, что соответствует группе захвата (например $1).
Что касается того, что вы пробовали :
Вместо того, чтобы использовать ваше регулярное выражение
\$.+?(?=\.)напрямую с оператором на основе регулярного выражения , вы использовали дословный результат явного вызова в качестве операнда поиска (первый операнд RHS) для , который затем снова интерпретируется как регулярное выражение.-replace[regex].Match()-replace- Однако, чтобы дословно использовать строку в качестве операнда
-replaceпоиска , любые метасимволы регулярных выражений, т. Е. Символы со специальным синтаксическим значением, должны быть\экранированы , например дословно$в вашей строке, что вы можете сделать с[regex]::Escape($s)
- Однако, чтобы дословно использовать строку в качестве операнда
Кроме того, вы использовали заменяющий операнд со встроенным
$символом. что вы хотели интерпретировать дословно , но$в операнде замены есть метасимвол , относящийся к заполнителям, таким как$&.Чтобы дословно использовать строку в качестве операнда
-replaceзамены , необходимо программно экранировать встроенные$символы. as$$[1] :
Самый простой подход - использовать[string]метод замены литерала-подстроки типа.Replace():$replacementOperand = '$foo' 'value is: (value)' -replace '\(value\)', $replacementOperand.Replace('$', '$$')
Таким образом, ваш исходный подход должен был бы использовать следующую команду, но обратите внимание, что решение Ryszard в целом намного проще:
$beta = $alpha -replace [regex]::replace($s), $newChunk.Replace('$', '$$')
[1] Ситуационно вы можете уйти , не убежать, потому что $-prefixed маркер , который не распознается как заполнитель остается нетронутым (например, 'bar' -replace 'r', '$x'ведет себя так же , как 'bar' -replace 'r', '$$x'), но единственным надежным решением является избежать дословные $символов. удвоив их.