Tudo o que você queria saber sobre substituição de variáveis em strings
Há muitas maneiras de usar variáveis em cadeias de caracteres. Estou chamando essa variável de substituição, mas estou me referindo a sempre que você quiser formatar uma cadeia de caracteres para incluir valores de variáveis. Isso é algo que muitas vezes me pego explicando para novos scripters.
Nota
A versão original deste artigo apareceu no blog escrito por @KevinMarquette. A equipe do PowerShell agradece Kevin por compartilhar esse conteúdo conosco. Por favor, confira seu blog em PowerShellExplained.com.
Concatenação
A primeira classe de métodos pode ser referida como concatenação. É basicamente pegar várias cordas e juntá-las. Há uma longa história de uso de concatenação para criar cadeias de caracteres formatadas.
$name = 'Kevin Marquette'
$message = 'Hello, ' + $name
A concatenação funciona bem quando há apenas alguns valores para adicionar. Mas isso pode se complicar rapidamente.
$first = 'Kevin'
$last = 'Marquette'
$message = 'Hello, ' + $first + ' ' + $last + '.'
Este exemplo simples já está ficando mais difícil de ler.
Substituição variável
O PowerShell tem outra opção mais fácil. Você pode especificar suas variáveis diretamente nas cadeias de caracteres.
$message = "Hello, $first $last."
O tipo de aspas que você usa ao redor da string faz a diferença. Uma cadeia de aspas duplas permite a substituição, mas uma única cadeia de aspas não. Há momentos em que você quer um ou outro, então você tem uma opção.
Substituição de comandos
As coisas ficam um pouco complicadas quando você começa a tentar obter os valores das propriedades em uma cadeia de caracteres. É aqui que muitas pessoas novas são tropeçadas. Primeiro deixe-me mostrar-lhe o que eles acham que deve funcionar (e ao pé da letra quase parece que deveria).
$directory = Get-Item 'c:\windows'
$message = "Time: $directory.CreationTime"
Você estaria esperando para obter o CreationTime
$directory
fora do , mas em vez disso, você recebe isso Time: c:\windows.CreationTime
como seu valor. A razão é que este tipo de substituição só vê a variável base. Ele considera o período como parte da cadeia de caracteres, então ele para de resolver o valor mais profundamente.
Acontece que esse objeto fornece uma cadeia de caracteres como um valor padrão quando colocado em uma cadeia de caracteres.
Em vez disso, alguns objetos dão o nome do tipo, como System.Collections.Hashtable
. Apenas algo a observar.
O PowerShell permite que você execute comandos dentro da cadeia de caracteres com uma sintaxe especial. Isso nos permite obter as propriedades desses objetos e executar qualquer outro comando para obter um valor.
$message = "Time: $($directory.CreationTime)"
Isso funciona muito bem para algumas situações, mas pode ficar tão louco quanto concatenação se você tiver apenas algumas variáveis.
Execução de comando
Você pode executar comandos dentro de uma cadeia de caracteres. Apesar de ter essa opção, não gosto. Ele fica confuso rapidamente e difícil de depurar. Eu executo o comando e salvo em uma variável ou uso uma cadeia de caracteres de formato.
$message = "Date: $(Get-Date)"
Formatar cadeia de caracteres
O .NET tem uma maneira de formatar cadeias de caracteres com as quais acho bastante fácil trabalhar. Primeiro, deixe-me mostrar o método estático para ele antes de mostrar o atalho do PowerShell para fazer a mesma coisa.
# .NET string format string
[string]::Format('Hello, {0} {1}.',$first,$last)
# PowerShell format string
'Hello, {0} {1}.' -f $first, $last
O que está acontecendo aqui é que a string é analisada para os tokens {0}
e {1}
, em seguida, usa esse número para escolher entre os valores fornecidos. Se você quiser repetir um valor em algum lugar na cadeia de caracteres, poderá reutilizar esse número de valores.
Quanto mais complicada a cadeia de caracteres fica, mais valor você obtém dessa abordagem.
Formatar valores como matrizes
Se a linha de formato ficar muito longa, você pode colocar seus valores em uma matriz primeiro.
$values = @(
"Kevin"
"Marquette"
)
'Hello, {0} {1}.' -f $values
Isso não é splatting porque estou passando toda a matriz, mas a ideia é semelhante.
Formatação avançada
Eu intencionalmente chamei isso como vindo do .NET porque há muitas opções de formatação já bem documentadas nele. Existem maneiras internas de formatar vários tipos de dados.
"{0:yyyyMMdd}" -f (Get-Date)
"Population {0:N0}" -f 8175133
20211110
Population 8,175,133
Eu não vou entrar neles, mas eu só queria que você saiba que este é um motor de formatação muito poderoso, se você precisar.
Juntando cadeias de caracteres
Às vezes, você realmente quer concatenar uma lista de valores juntos. Há um -join
operador que pode fazer isso por você. Ele ainda permite que você especifique um caractere para unir entre as cadeias de caracteres.
$servers = @(
'server1'
'server2'
'server3'
)
$servers -join ','
Se você quiser -join
algumas cadeias de caracteres sem um separador, você precisa especificar uma cadeia de caracteres ''
vazia .
Mas se isso é tudo o que você precisa, há uma opção mais rápida.
[string]::Concat('server1','server2','server3')
[string]::Concat($servers)
Também vale a pena ressaltar que você também -split
pode fazer cordas.
Join-Path
Isso geralmente é negligenciado, mas é um ótimo cmdlet para criar um caminho de arquivo.
$folder = 'Temp'
Join-Path -Path 'c:\windows' -ChildPath $folder
O melhor de tudo isso é que ele funciona as barras invertidas corretamente quando junta os valores. Isso é especialmente importante se você estiver usando valores de usuários ou arquivos de configuração.
Isso também vai bem com Split-Path
e Test-Path
. Eu também abordo estes no meu post sobre como ler e salvar em arquivos.
Strings são matrizes
Eu preciso mencionar a adição de strings aqui antes de continuar. Lembre-se de que uma cadeia de caracteres é apenas uma matriz de caracteres. Quando você adiciona várias cadeias de caracteres juntas, uma nova matriz é criada a cada vez.
Veja este exemplo:
$message = "Numbers: "
foreach($number in 1..10000)
{
$message += " $number"
}
Parece muito básico, mas o que você não vê é que cada vez que uma string é adicionada a $message
isso, uma string totalmente nova é criada. A memória é alocada, os dados são copiados e o antigo é descartado.
Não é grande coisa quando é feito apenas algumas vezes, mas um loop como este realmente exporia o problema.
Construtor de Strings
StringBuilder também é muito popular para construir cadeias de caracteres grandes a partir de muitas cadeias de caracteres menores. A razão é porque ele apenas coleta todas as cadeias de caracteres que você adiciona a ele e só concatena todas elas no final quando você recupera o valor.
$stringBuilder = New-Object -TypeName "System.Text.StringBuilder"
[void]$stringBuilder.Append("Numbers: ")
foreach($number in 1..10000)
{
[void]$stringBuilder.Append(" $number")
}
$message = $stringBuilder.ToString()
Mais uma vez, isso é algo para o qual estou entrando em contato com o .NET. Eu não uso mais com frequência, mas é bom saber que está lá.
Delimitação com suportes
Isso é usado para concatenação de sufixos dentro da cadeia de caracteres. Às vezes, sua variável não tem um limite de palavras limpo.
$test = "Bet"
$tester = "Better"
Write-Host "$test $tester ${test}ter"
Obrigado /u/real_parbold por isso.
Aqui está uma alternativa a esta abordagem:
Write-Host "$test $tester $($test)ter"
Write-Host "{0} {1} {0}ter" -f $test, $tester
Eu pessoalmente uso string de formato para isso, mas isso é bom saber incase você vê-lo na natureza.
Localizar e substituir tokens
Embora a maioria desses recursos limite sua necessidade de rolar sua própria solução, há momentos em que você pode ter grandes arquivos de modelo onde deseja substituir cadeias de caracteres dentro.
Vamos supor que você tenha puxado um modelo de um arquivo que tem muito texto.
$letter = Get-Content -Path TemplateLetter.txt -RAW
$letter = $letter -replace '#FULL_NAME#', 'Kevin Marquette'
Você pode ter muitos tokens para substituir. O truque é usar um token muito distinto que seja fácil de encontrar e substituir. Eu tendo a usar um caractere especial em ambas as extremidades para ajudar a distingui-lo.
Recentemente, encontrei uma nova forma de abordar esta questão. Eu decidi deixar esta seção aqui porque este é um padrão que é comumente usado.
Substitua vários tokens
Quando tenho uma lista de tokens que preciso substituir, adoto uma abordagem mais genérica. Eu os colocaria em uma hashtable e iteraria sobre eles para fazer a substituição.
$tokenList = @{
Full_Name = 'Kevin Marquette'
Location = 'Orange County'
State = 'CA'
}
$letter = Get-Content -Path TemplateLetter.txt -RAW
foreach( $token in $tokenList.GetEnumerator() )
{
$pattern = '#{0}#' -f $token.key
$letter = $letter -replace $pattern, $token.Value
}
Esses tokens podem ser carregados de JSON ou CSV, se necessário.
ExecutionContext ExpandString
Há uma maneira inteligente de definir uma cadeia de substituição com aspas simples e expandir as variáveis mais tarde. Veja este exemplo:
$message = 'Hello, $Name!'
$name = 'Kevin Marquette'
$string = $ExecutionContext.InvokeCommand.ExpandString($message)
A chamada para .InvokeCommand.ExpandString
no contexto de execução atual usa as variáveis no escopo atual para substituição. O importante aqui é que o $message
pode ser definido muito cedo antes mesmo que as variáveis existam.
Se expandirmos um pouco isso, podemos realizar essa substituição repetidamente com valores diferentes.
$message = 'Hello, $Name!'
$nameList = 'Mark Kraus','Kevin Marquette','Lee Dailey'
foreach($name in $nameList){
$ExecutionContext.InvokeCommand.ExpandString($message)
}
Continuar com esta ideia; Você pode estar importando um modelo de e-mail grande de um arquivo de texto para fazer isso. Tenho de agradecer a Mark Kraus por esta sugestão.
O que funciona melhor para si
Eu sou um fã da abordagem de string de formato. Eu definitivamente faço isso com as cadeias de caracteres mais complicadas ou se houver várias variáveis. Em qualquer coisa que seja muito curta, posso usar qualquer uma delas.
Mais alguma coisa?
Eu cobri muito terreno neste. Minha esperança é que você saia aprendendo algo novo.
Ligações
Se você quiser saber mais sobre os métodos e recursos que tornam a interpolação de cadeia de caracteres possível, consulte a lista a seguir para obter a documentação de referência.
- A concatenação usa o operador de adição
- A substituição de variáveis e comandos segue as regras de cotação
- A formatação usa o operador de formato
- A junção de cadeias de caracteres usa o operador de junção e as referências
Join-Path
, mas você também pode ler sobreJoin-String
- As matrizes estão documentadas em Sobre matrizes
- StringBuilder é uma classe .NET, com sua própria documentação
- Chaves em strings também são abordadas nas regras de cotação
- A substituição de token usa o operador de substituição
- O
$ExecutionContext.InvokeCommand.ExpandString()
método tem documentação de referência da API .NET
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários