![Powershell: una variable dentro de una variable; Concepción variable](https://rvso.com/image/1449093/Powershell%3A%20una%20variable%20dentro%20de%20una%20variable%3B%20Concepci%C3%B3n%20variable.png)
Entonces, la forma más fácil de explicar mi problema es mostrarles esta versión simplificada de lo que estoy tratando de hacer:
PS C:\> $a = 'hello'
PS C:\> $a
hello
PS C:\> $b = '$a world!'
PS C:\> $b
$a world!
Ahora lo que realmente quiero es que la invocación de $b devuelva '¡hola mundo!' pero aparentemente no puedo llamar a una variabledentrootra variable como esta. ¿Alguien tiene alguna sugerencia o solución alternativa? Siento que me estoy perdiendo algo obvio aquí.
Editar: una versión más precisa de lo que estoy intentando hacer:
PS C:\> $selHost = (get-content c:\scripts\hosts.txt)[0]
PS C:\> $selhost
spr-it-minion
PS C:\> $a = (get-content c:\scripts\config.txt)[1]
PS C:\> $a
$selhost Is Offline!
PS C:\> $b = "$a"
PS C:\> $b
$selhost Is Offline!
Así que estoy sacando la primera línea de hosts.txt y configurándola en $selhost, que es simplemente 'spr-it-minion'. Luego saco la segunda línea de config.txt, que es solo la cadena '$selhost is offline!' con la esperanza de que cuando llame a $a aparezca '¡spr-it-minion está desconectado!' y no estoy seguro de qué hacer.
Edición II: el contenido de hosts.txt y config.txt respectivamente.
hosts.txt:
spr-it-minion
spr-saflok
spr-crosby
spr-vmhost01
spr-vmhost02
spr-vmhost03
configuración.txt:
172.31.1.124
$selhost Is Offline!
$selhost Is Offline!
[email protected]
[email protected]
Edición III: ElPastebina mi guión real si alguno de ustedes está interesado.
Línea 15: Configuré $alertSubject en la cadena "¡$selhost está desconectado!" sin comillas ni nada.
Línea 82: uso $alertSubject como línea de asunto de una alerta de correo electrónico con la esperanza de que la variable que contiene tenga su valor representado como: "¡spr-it-minion está desconectado!" pero cuando recibo el correo electrónico o intento escribir-host $alertSubject en cualquier parte del script, simplemente dice "¡$selhost está desconectado!"
Respuesta1
Al definir variables en PowerShell, las comillas simples ( '
) significan que desea la versión literal de la cadena. Utilice comillas dobles ( "
) si desea permitir la expansión variable:
PS C:\> $a = "hello"
PS C:\> $a
hello
PS C:\> $b = "$a world!"
PS C:\> $b
hello world!
Más información:
- Comillas simples versus comillas dobles en PowerShell: ¿Cuál es la diferencia?
- Hacer referencia a variables y valores de variables
Editar después de los comentarios:
Para su ejemplo en el que extrae la línea de un archivo, es un poco más complicado ya que extrae la línea como una cadena literal.
La forma más sencilla (en mi opinión) sería utilizar elReemplazarmétodo; algo como:
$selHost = (get-content c:\scripts\hosts.txt)[0]
$a = ((get-content c:\scripts\config.txt)[1]).replace('$selhost', $selHost)
Respuesta2
Cuando lees una cadena que contiene un nombre de variable de un archivo a una variable, necesitarás algo más que comillas dobles para provocar la expansión de la cadena. Hay una herramienta que es relevante aquí. Se llama ExpandString. Eche un vistazo a este código de muestra:
$selhost = 'spr-it-minion'
$b = '$selhost is offline!'
$c = $ExecutionContext.InvokeCommand.ExpandString($b)
$c
Lo que está pasando aquí es que primero le he dado valores literales a $selhost y $b, similares a los que leería en los archivos que está utilizando. Por supuesto, $b no es correcto, porque la referencia a $selhost no está resuelta, como se describe en la respuesta aceptada. Pero $c obtiene el valor producido al expandir $selhost, que puede usar en su salida.
Dejaré la aplicación de esto a su caso como ejercicio de codificación.
Respuesta3
Lo que intenta hacer aquí es Powershell dinámico, es decir, crear una cadena que contenga un comando de Powershell y luego hacer que Powershell ejecute ese comando. Puedes hacer esto con Invoke-Expression, por ejemplo:
$alertSubject = Invoke-Expression -Command "`"$((Get-Content '.\config.txt')[1])`""
Aunque, por razones de mantenimiento, es posible que desees dividirlo en algo como:
$config1 = (Get-Content '.\config.txt')[1]
$alertSubject = Invoke-Expression -Command "`"$config1`""
Las comillas invertidas están ahí porque el comando que realmente desea ejecutar es:
"$selhost is offline!"
Las comillas externas permiten $config1
expandirse antes de pasar el valor Invoke-Expression
. Ese valor debe incluir comillas dobles para que $selhost
pueda expandirse cuando se invoque el comando.
Alternativamente, puedes poner comillas dobles en el archivo de configuración:
172.31.1.124
"$selhost Is Offline!"
"$selhost Is Offline!"
[email protected]
[email protected]
y luego solo tener
$alertSubject = Invoke-Expression -Command $config1
En este patrón, las comillas dobles exteriores $config1
se han eliminado porque son redundantes.
Respuesta4
El método de reemplazo funciona bien para la sustitución de variables dentro de variables, incluso cuando se llama a PowerShell desde Autohotkey:
uri = file$k.doc
psScript2 =
(
param($param1)
for($k=1; $k -le 6; $k++){
$uri = $param1.replace('$k',"$k")
echo $uri
}
)
Run PowerShell.exe -noexit -Command &{%psScript2%} '%uri%',, show
return
Tenga en cuenta el uso de comillas simples para buscar la variable interna que se sustituirá por el contenido de la variable externa.
El resultado es:
file1.doc
file2.doc
etc.