Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Hay muchas maneras de usar variables en cadenas. Estoy llamando a esta sustitución de variables, pero me refiero a cualquier momento en que quiera dar formato a una cadena para incluir valores de variables. Esto es algo que a menudo me encuentro explicando a nuevos scripters.
Nota:
La versión original de este artículo apareció en el blog escrito por @KevinMarquette. El equipo de PowerShell agradece a Kevin por compartir este contenido con nosotros. Consulte su blog en PowerShellExplained.com.
Concatenación
La primera clase de métodos se puede denominar concatenación. Básicamente, toma varias cadenas y las une. Hay un largo historial de uso de la concatenación para crear cadenas con formato.
$name = 'Kevin Marquette'
$message = 'Hello, ' + $name
La concatenación funciona bien cuando solo hay algunos valores que se van a agregar. Pero esto puede complicarse rápidamente.
$first = 'Kevin'
$last = 'Marquette'
$message = 'Hello, ' + $first + ' ' + $last + '.'
Este ejemplo sencillo ya es más difícil de leer.
Sustitución de variables
PowerShell tiene otra opción que es más fácil. Puede especificar las variables directamente en las cadenas.
$message = "Hello, $first $last."
El tipo de comillas que se usan alrededor de la cadena marca una diferencia. Una cadena entre comillas dobles permite la sustitución, pero no una sola cadena entre comillas. Hay veces que quieres una o la otra para que tengas una opción.
Sustitución de comandos
Las cosas se complican un poco al empezar a intentar obtener los valores de las propiedades en una cadena. Aquí es donde muchas personas nuevas se levantan. En primer lugar, déjame mostrar lo que piensan que deberían funcionar (y en el valor facial casi parece que debería).
$directory = Get-Item 'C:\windows'
$message = "Time: $directory.CreationTime"
Se espera que salga CreationTime de $directory, pero en su lugar obtendrá esto Time: C:\windows.CreationTime como su valor. La razón es que este tipo de sustitución solo ve la variable base. Considera el punto como parte de la cadena para que deje de resolver el valor más profundo.
Esto sucede que este objeto proporciona una cadena como un valor predeterminado cuando se coloca en una cadena.
Algunos objetos le proporcionan el nombre de tipo en su lugar, como System.Collections.Hashtable. Sólo hay algo que ver.
PowerShell permite ejecutar comandos dentro de la cadena con una sintaxis especial. Esto nos permite obtener las propiedades de estos objetos y ejecutar cualquier otro comando para obtener un valor.
$message = "Time: $($directory.CreationTime)"
Esto funciona bien para algunas situaciones, pero puede ser tan loco como la concatenación si solo tiene algunas variables.
Ejecución de comandos
Puede ejecutar comandos dentro de una cadena. Aunque tengo esta opción, no me gusta. Se desordena rápidamente y es difícil de depurar. Ejecuto el comando y guardo en una variable o uso una cadena de formato.
$message = "Date: $(Get-Date)"
Cadena de formato
.NET tiene una manera de dar formato a las cadenas con las que encuentro bastante fácil de trabajar. En primer lugar, déjeme mostrar el método estático para él antes de mostrar el acceso directo de PowerShell para hacer lo mismo.
# .NET string format string
[string]::Format('Hello, {0} {1}.',$first,$last)
# PowerShell format string
'Hello, {0} {1}.' -f $first, $last
Lo que sucede aquí es que la cadena se analiza para los tokens {0} y {1}, a continuación, usa ese número para elegir entre los valores proporcionados. Si desea repetir un valor en algún lugar de la cadena, puede reutilizar ese número de valores.
Cuanto más complicado sea la cadena, más valor obtendrá de este enfoque.
Dar formato a valores como matrices
Si la línea de formato es demasiado larga, puede colocar primero los valores en una matriz.
$values = @(
"Kevin"
"Marquette"
)
'Hello, {0} {1}.' -f $values
Esto no es una expansión porque estoy pasando toda la matriz en, pero la idea es similar.
Formato avanzado
Lo he llamado intencionadamente como procedente de .NET porque hay muchas opciones de formato ya bien documentadas . Hay maneras integradas de dar formato a varios tipos de datos.
"{0:yyyyMMdd}" -f (Get-Date)
"Population {0:N0}" -f 8175133
20211110
Population 8,175,133
No voy a entrar en ellos, pero sólo quería informarte de que esto es un motor de formato muy potente si lo necesitas.
Combinar cadenas
A veces realmente desea concatenar una lista de valores juntos. Hay un -join operador que puede hacerlo para usted. Incluso permite especificar un carácter para combinar entre las cadenas.
$servers = @(
'server1'
'server2'
'server3'
)
$servers -join ','
Si desea algunas -join cadenas sin un separador, debe especificar una cadena ''vacía.
Pero si eso es todo lo que necesita, hay una opción más rápida.
[string]::Concat('server1','server2','server3')
[string]::Concat($servers)
También vale la pena señalar que también -split puede cadenas.
Join-Path
Esto suele pasarse por alto, pero es un excelente cmdlet para crear una ruta de acceso de archivo.
$folder = 'Temp'
Join-Path -Path 'C:\windows' -ChildPath $folder
Lo mejor de esto es que funciona correctamente las barras diagonales inversas cuando coloca los valores juntos. Esto es especialmente importante si está tomando valores de usuarios o archivos de configuración.
Esto también va bien con Split-Path y Test-Path. También los cubriré en mi publicación sobre la lectura y el guardado en archivos.
Las cadenas son matrices
Necesito mencionar la adición de cadenas aquí antes de continuar. Recuerde que una cadena es simplemente una matriz de caracteres. Al agregar varias cadenas juntas, se crea una nueva matriz cada vez.
Examine este ejemplo:
$message = "Numbers: "
foreach($number in 1..10000)
{
$message += " $number"
}
Parece muy básico, pero lo que no ve es que cada vez que se agrega una cadena a $message que se crea una nueva cadena completa. La memoria se asigna, los datos se copian y se descarta el anterior.
No es una gran cosa cuando solo se hace unas pocas veces, pero un bucle como este realmente expondría el problema.
StringBuilder
StringBuilder también es muy popular para crear cadenas grandes a partir de muchas cadenas más pequeñas. La razón por la que se debe a que solo recopila todas las cadenas que se agregan a ella y solo concatena todas ellas al final cuando se recupera el valor.
$stringBuilder = New-Object -TypeName "System.Text.StringBuilder"
[void]$stringBuilder.Append("Numbers: ")
foreach($number in 1..10000)
{
[void]$stringBuilder.Append(" $number")
}
$message = $stringBuilder.ToString()
De nuevo, esto es algo para lo que estoy llegando a .NET. Ya no lo uso, pero es bueno saber que está ahí.
Delineación con llaves
Se usa para la concatenación de sufijos dentro de la cadena. A veces, la variable no tiene un límite de palabra limpio.
$test = "Bet"
$tester = "Better"
Write-Host "$test $tester ${test}ter"
Gracias Por eso.u/real_parbold
Esta es una alternativa a este enfoque:
Write-Host "$test $tester $($test)ter"
Write-Host "{0} {1} {0}ter" -f $test, $tester
Personalmente uso la cadena de formato para esto, pero esto es bueno saber en caso de que lo veas en la naturaleza.
Buscar y reemplazar tokens
Aunque la mayoría de estas características limitan la necesidad de implementar su propia solución, hay ocasiones en las que es posible que tenga archivos de plantilla grandes en los que quiera reemplazar cadenas dentro.
Supongamos que ha extraído una plantilla de un archivo que tiene mucho texto.
$letter = Get-Content -Path TemplateLetter.txt -RAW
$letter = $letter -replace '#FULL_NAME#', 'Kevin Marquette'
Es posible que tenga un montón de tokens para reemplazar. El truco es usar un token muy distinto que es fácil de encontrar y reemplazar. Tienden a usar un carácter especial en ambos extremos para ayudar a distinguirlo.
Recientemente encontré una nueva manera de abordar esto. Decidí dejar esta sección aquí porque se trata de un patrón que se usa habitualmente.
Reemplazar varios tokens
Cuando tengo una lista de tokens que necesito reemplazar, tomo un enfoque más genérico. Los colocaría en una tabla hash e iteración sobre ellos para hacer el reemplazo.
$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
}
Esos tokens se pueden cargar desde JSON o CSV si es necesario.
ExecutionContext ExpandString
Hay una manera inteligente de definir una cadena de sustitución con comillas simples y expandir las variables más adelante. Examine este ejemplo:
$message = 'Hello, $Name!'
$name = 'Kevin Marquette'
$string = $ExecutionContext.InvokeCommand.ExpandString($message)
La llamada a InvokeCommand.ExpandString en el contexto de ejecución actual usa las variables en el ámbito actual para la sustitución. La clave aquí es que se $message puede definir muy pronto antes de que existan las variables.
Si expandimos en ese solo un poco, podemos realizar esta sustitución sobre y más con valores diferentes.
$message = 'Hello, $Name!'
$nameList = 'Mark Kraus','Kevin Marquette','Lee Dailey'
foreach($name in $nameList){
$ExecutionContext.InvokeCommand.ExpandString($message)
}
Para seguir adelante con esta idea; Podría importar una plantilla de correo electrónico grande desde un archivo de texto para hacerlo. Tengo que agradecer a Mark Kraus por esta sugerencia.
Lo que sea que sea lo mejor para usted
Soy fan del enfoque de cadena de formato. Definitivamente lo hago con las cadenas más complicadas o si hay varias variables. En todo lo que sea muy corto, puedo usar cualquiera de estos.
¿Algo más?
He cubierto un montón de terreno en este. Mi esperanza es que te alejas aprendiendo algo nuevo.
Enlaces
Si desea obtener más información sobre los métodos y características que hacen posible la interpolación de cadenas, consulte la lista siguiente para obtener la documentación de referencia.
- La concatenación usa el operador de suma
- La sustitución de variables y comandos sigue las reglas de comillas
- El formato usa el operador format
- La combinación de cadenas usa el operador join y las referencias
Join-Path, pero también puede leer sobreJoin-String - Las matrices se documentan en Acerca de las matrices
- StringBuilder es una clase .NET, con su propia documentación
- Las llaves de las cadenas también se tratan en las reglas de comillas.
- El reemplazo de tokens usa el operador replace
- El
$ExecutionContext.InvokeCommand.ExpandString()método tiene documentación de referencia de la API de .NET