Powershell - substituir com comportamento estranho
Isso está me deixando louco! Gostaria de receber qualquer indicação sobre o que está acontecendo, por favor!
$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"
Isso produz a seguinte saída:
Alpha is: aaa.bbb.$connection.ccc.ddd
Matched chunk is: $connection New chunk is: '$connection'
Beta is: aaa.bbb.$connection.ccc.ddd
Estou tentando identificar / combinar sequências de caracteres em um caminho que começa com o literal '$' e continua até, mas não inclui um ponto literal "." Caracteres. No código de exemplo acima, a string seria "$ connection".
Em seguida, preciso envolver essa string entre aspas simples, portanto, no exemplo acima, o valor $ newChunk se tornaria '$ connection' incluindo as aspas simples.
Em seguida, preciso substituir o valor correspondente pelo novo valor entre aspas simples na string original. Não importa o que eu tente (mesmo com o método [regex] :: match também), as aspas simples são removidas. Então, efetivamente, estou tentando transformar:
aaa.bbb.$connection.ccc.ddd
para dentro
aaa.bbb.'$connection'.ccc.ddd
Estou usando o PowerShell 7.1 e gostaria muito que alguém me dissesse por que isso não funciona. Obrigado!
Respostas
Usar
$beta = $alpha -replace '\$[^.]+', "'$&'"
Veja a prova .
Explicação
--------------------------------------------------------------------------------
\$ '$'
--------------------------------------------------------------------------------
[^.]+ any character except: '.' (1 or more times
(matching the most amount possible))
O $&é o espaço reservado para toda a partida.
A resposta útil de Ryszard Czech é definitivamente a melhor solução : genericamente, referir-se ao que o operador baseado em regex -replace combinou, em seu operando de substituição, com placeholder$& é a solução mais simples e robusta.
Veja esta resposta para outros espaços reservados que você pode usar, como o que precedeu ( $`) ou sucedeu ( $') a correspondência, ou o que um grupo de captura correspondeu (por exemplo $1).
Quanto ao que você tentou :
Em vez de usar seu regex
\$.+?(?=\.)diretamente com o operador baseado em regex , você usou o resultado literal de uma chamada explícita como o operando de pesquisa (primeiro operando RHS) para , que é novamente interpretado como um regex.-replace[regex].Match()-replace- No entanto, para usar uma string literalmente como o operando de
-replacepesquisa , quaisquer metacaracteres regex - ou seja, caracteres com significado sintático especial - devem ter\escape , como o literal$em sua string, o que você pode fazer com[regex]::Escape($s)
- No entanto, para usar uma string literalmente como o operando de
Além disso, você usou um operando de substituição que tinha um char embutido
$. que você pretendia ser interpretado literalmente , mas$no operando de substituição está um metacaractere , referindo-se a marcadores de posição como$&.Para usar uma string literalmente como operando de
-replacesubstituição , você deve escapar de forma programática os caracteres incorporados$. as$$[1] :
A abordagem mais simples é usar o[string]método de substituição literal-substring do tipo.Replace():$replacementOperand = '$foo' 'value is: (value)' -replace '\(value\)', $replacementOperand.Replace('$', '$$')
Assim, sua abordagem original teria que usar o seguinte comando - mas observe que a solução de Ryszard é muito mais simples no geral:
$beta = $alpha -replace [regex]::replace($s), $newChunk.Replace('$', '$$')
[1] Situacionalmente, você pode escapar sem escapar, porque um $token com prefixo que não é reconhecido como um espaço reservado é deixado intocado (por exemplo, 'bar' -replace 'r', '$x'se comporta da mesma forma que 'bar' -replace 'r', '$$x'), mas a única solução robusta é escapar literalmente dos $caracteres. dobrando-os.