¿Cómo concateno cadenas y variables en PowerShell?

Supongamos que tengo el siguiente fragmento:

$assoc = New-Object PSObject -Property @{
    Id = 42
    Name = "Slim Shady"
    Owner = "Eminem"
}

Write-Host $assoc.Id + "  -  "  + $assoc.Name + "  -  " + $assoc.Owner

Espero que este fragmento muestre:

42 - Slim Shady - Eminem

Pero en cambio muestra:

42 + - + Slim Shady + - + Eminem

Lo que me hace pensar que + El operador no es apropiado para concatenar cadenas y variables.

¿Cómo debería abordar esto con PowerShell?

preguntado el 27 de febrero de 13 a las 13:02

tu codigo funciona if todos los elementos son cadenas y usted encierra la expresión entre paréntesis: Write-host ($assoc.Id.ToString() + " - " + $assoc.Name + " - " + $assoc.Owner) aquí $assoc.Id es un Int32 entonces tenemos que usar su representación de cadena. De lo contrario, PS intenta realizar una suma aritmética en lugar de una concatenación. -

Dada la cantidad de visitas, pensé que era apropiado reparar el texto de esta pregunta, aunque mis ediciones cambiaron bastante el contenido. Traté de mantener intacta la terminología/redacción y el espíritu de la pregunta, mientras la mejoraba lo suficiente para que pueda reabrirse. -

22 Respuestas

Write-Host "$($assoc.Id) - $($assoc.Name) - $($assoc.Owner)"

Consulte las Especificación de idioma de Windows PowerShell, versión 3.0, p34, expansión de subexpresiones.

respondido 18 mar '16, 19:03

¿Por qué el $($nombre) frente a solo $nombre? ¿Es esto simplemente defensivo de la misma manera que en bash usando ${name}? - danny grapa

Esto no es técnicamente concatenación. - TravisEz13

@DannyStaple la pregunta tiene sido editado tanto que la respuesta ya no tiene sentido. En el ejemplo de Slim Shady, sí "... $name ..." funcionará de todos modos, pero en la pregunta original a la que responde esta respuesta, la pregunta es cómo acceder a las propiedades del objeto. Así que si $name.id -eq 42 luego "... $name.id ..." no funcionaría como usted quiere porque se renderizaría como ... @{id=42}.id ... en lugar de lo deseado ... 42 ... Para eso, usa el método de la respuesta. "... $($name.id) ...". Estoy marcando la pregunta para editarla más tarde. - jeff puckett

Muchas gracias por señalarme la Especificación de lenguaje de PowerShell. Como principiante, siempre me ha confundido por qué PowerShell no viene con un tutorial oficial. Esta especificación de idioma se parece a lo que estoy buscando. ¡Gracias de nuevo! - RayLuo

Esto no funciona para distribuir cadenas en varias líneas. En su lugar, use ( $string1, $string2, $string3 ) -join "" or ($string1 + $string2 + $string3). Con estos métodos, puede tener espacios en blanco (espacios, tabulaciones y saltos de línea) entre las cadenas, pero asegúrese de que (1) cada cadena tenga una coma/espacio después de ella en la misma línea, (2) use la marca de retroceso carácter ` al final de cualquier línea vacía entre su código, y (3) si usa -join, el soporte final y el -join el operador debe estar en la misma línea - david f

Hay una diferencia entre comillas simples y dobles. (Estoy usando PowerShell 4).

Puedes hacer esto (como Benjamín dijo):

$name = 'Slim Shady'
Write-Host 'My name is'$name
-> My name is Slim Shady

O puedes hacer esto:

$name = 'Slim Shady'
Write-Host "My name is $name"
-> My name is Slim Shady

Las comillas simples son literales, genere la cadena exactamente así, por favor. Las comillas dobles son para cuando desea que se realice un procesamiento previo (como variables, caracteres especiales, etc.)

De modo que:

$name = "Marshall Bruce Mathers III"
Write-Host "$name"
-> Marshall Bruce Mathers III

Mientras:

$name = "Marshall Bruce Mathers III"
Write-Host '$name'
-> $name

(Encuentro Cómo hacerlo: caracteres de escape, delimitadores y comillas bueno como referencia).

Respondido el 27 de junio de 20 a las 11:06

También funciona con 1.0. - smit johnth

Esta regla de comillas y demostración para la concatenación es aplicable a las secuencias de comandos de shell 'nix (por ejemplo, Bash), además de PowerShell. El factor de portabilidad solo gana mi voto. - BuvinJ

Me avergüenza decir que mi secuencia de comandos estaba depurando con "" pero escribiendo comandos con cadenas y variables usando '' y fueron horas de trabajo y esta respuesta para encontrar lo que había hecho mal. ¡Increíble! - kyle burkett

powershell es ordenado y pondrá un espacio entre la cadena y el contenido de la variable en Write-Host 'My name is'$name - Timo

También puedes usar -join

P.ej

$var = -join("Hello", " ", "world");

Asignaría "Hola mundo" a $var.

Así que para la salida, en una línea:

Write-Host (-join("Hello", " ", "world"))

Respondido 01 Oct 20, 08:10

al menos este podría usarse en foreach - semidiós

Agregue que si está usando comandos como entradas, envuelva el comando dentro de $().....por ejemplo... -join($(cmd1), ",", $(cmd2)) ...me llevó también largo para averiguar como soy nuevo en PowerShell - S. Derretido

@S.Melted por qué envolver dentro $()? - AlbatrosCafe

Después de una revisión adicional, solo () es necesario para mi necesidad. Por ejemplo: -join("Timestamp: ", Get-Date) da un error, mientras -join("Timestamp: ", (Get-Date)) funciona bien Sin embargo, este explica cuando $() sería necesario. - S. Derretido

Write-Host -join("Hello", " ", "world") no se unirá como el todo join el argumento necesita corchetes que incluyan el nombre del arg = join. - Timo

Una forma es:

Write-Host "$($assoc.Id)  -  $($assoc.Name)  -  $($assoc.Owner)"

Otro es:

Write-Host  ("{0}  -  {1}  -  {2}" -f $assoc.Id,$assoc.Name,$assoc.Owner )

O simplemente (pero no me gusta ;) ):

Write-Host $assoc.Id  "  -  "   $assoc.Name  "  -  "  $assoc.Owner

Respondido el 27 de junio de 20 a las 11:06

No creo que el último funcione exactamente como cabría esperar. Ver pastebin aquí. Powershell agregará un espacio (aunque tenga dos aquí) a la salida para el espacio en blanco entre $assoc.Id y " (et al.). Es decir, la opción 1 te da Id__-__Name__-__Owner (dos espacios a cada lado de cada -), pero la opción 3 da Id___-___Name___-___Owner (Tres espacios). - ruffin

Quizás un pastebin más útil. $assoc.Id"###"$assoc.Name agregue espacios a cada lado del ###, donde "$($assoc.Id)###$($assoc.Name)" no se. - ruffin

Intente envolver lo que quiera imprimir entre paréntesis:

Write-Host ($assoc.Id + "  -  "  + $assoc.Name + "  -  " + $assoc.Owner)

Su código se interpreta como muchos parámetros que se pasan a Write-Host. Envolverlo entre paréntesis concatenará los valores y luego pasará el valor resultante como un solo parámetro.

Respondido el 27 de junio de 20 a las 11:06

+1, prefiero este formato cuando uso otros métodos como Write-Debug or Write-Verbose para incluir comillas dobles y valores de variables, como Write-Debug ('Running "cmdlet" with parameter $MyVar = ' + $MyVar + " at time " + (Get-Date -DisplayHint Time)) - Oso de TI

Sí, esto es concatenación de cadenas. No agrega líneas nuevas ni espacios adicionales. Le permite usar cadenas entre comillas simples o dobles. - LexH

Este truco es una verdadera concatenación y te permite hacer cadenas de varias líneas, como lo harías en .net. ¡Muy bueno para hacer sentencias SQL multilínea! ¿Por qué powershell no hace esto por defecto? - Cerebro2000

Hay muchas formas de hacerlo. Pero esta es la verdadera respuesta de la concatenación de cadenas. - ching muescas

¡Muchas gracias por esto! Estaba teniendo dificultades para construir el parámetro URI para Invoke-WebRequest y su solución fue la única que realmente funcionó: Invoke-WebRequest -uri ('http://mysvr/guestauth/app/rest/...'+$param1+'_'+$param2+'_something,count:10') - Andreas

Otra opción es:

$string = $assoc.ID
$string += " - "
$string += $assoc.Name
$string += " - "
$string += $assoc.Owner
Write-Host $string

El "mejor" método es probablemente el que sugirió CB:

Write-Host "$($assoc.Id)  -  $($assoc.Name)  -  $($assoc.Owner)"

Respondido el 27 de junio de 20 a las 11:06

Necesitas agregar el StringBuilder opción si te estás volviendo loco por los concat. ;^) - ruffin

seguramente hay una manera de canalizar las propiedades deseadas en un archivo externo, luego deserializarlas en una cadena de componentes unidos con guiones (?) - Jockey de código

Es difícil imaginar un enfoque peor que este. Las cadenas son inmutables, por lo que cada operación de concatenación produce una nueva cadena, copiando caracteres de la original. - wombatónfuego

En respuesta a Code Jockey, usar += puede producir una nueva cadena cada vez, pero para una cadena relativamente pequeña, agregar cadenas pequeñas adicionales como esta, a quién le importa. La claridad de lo que sucede es lo más importante y con PowerShell hacer que todo funcione es más importante que cualquier otra cosa. - Acción Dan

Mientras expresión:

"string1" + "string2" + "string3"

concatenará la cadena, debe colocar $ delante del paréntesis para que se evalúe como un solo argumento cuando se pasa a un comando de PowerShell. Ejemplo:

Write-Host $( "string1" + "string2" + "string3" )

Como beneficio adicional, si desea que abarque varias líneas, debe usar la sintaxis incómoda de acento grave al final de la línea (sin espacios ni caracteres a la derecha del acento grave).

Ejemplo:

Write-Host $(`
    "The rain in "        +`
    "Spain falls mainly " +`
    "in the plains"       )`
    -ForegroundColor Yellow

(En realidad, creo que PowerShell actualmente está un poco mal implementado al requerir acentos graves innecesarios entre paréntesis. Si Microsoft simplemente siguiera Python or TCL las reglas de paréntesis que le permiten poner tantos saltos de línea como desee entre el paréntesis inicial y final, entonces resolverían la mayoría de los problemas que a la gente no le gustan de PowerShell relacionados con la continuación de línea y la concatenación de cadenas.

Descubrí que a veces puedes dejar las tildes invertidas desactivadas en las continuaciones de línea entre paréntesis, pero es realmente escamoso e impredecible si funcionará... Es mejor simplemente agregar las tildes invertidas).

Respondido el 27 de junio de 20 a las 12:06

Debe colocar la expresión entre paréntesis para evitar que se traten como parámetros diferentes al cmdlet:

Write-Host ($assoc.Id + "  -  "  + $assoc.Name + "  -  " + $assoc.Owner)

Respondido el 27 de junio de 20 a las 11:06

Esto es obligatorio para Write-Debug - Frank

(Versión actual de PowerShell 5.1.17134.407)

Esto también funciona a partir de ahora:

$myVar = "Hello"

echo "${myVar} World"

Nota: esto solo funciona con comillas dobles

Respondido el 27 de junio de 20 a las 11:06

Aquí hay otra forma como alternativa:

Write-Host (" {0}  -  {1}  -  {2}" -f $assoc.Id, $assoc.Name, $assoc.Owner)

Respondido el 27 de junio de 20 a las 11:06

Solo quiero traer otra forma de hacer esto usando .NET Cadena.Formato:

$name = "Slim Shady"
Write-Host ([string]::Format("My name is {0}", $name))

contestado el 26 de mayo de 16 a las 19:05

¿Hay alguna ventaja de usar .NET? String.Format en lugar de la vieja llanura "{0}" -f $var? No veo el sentido de usar código .NET donde PowerShell simple puede hacer el trabajo... - dinei

@DineiRockenbach Probablemente no. Solo quería mencionar otro ejemplo. - Martín Brandl

Parece que tengo problemas con esto (y muchas otras cosas poco intuitivas) cada vez que uso PowerShell después de un tiempo sin usarlo, así que ahora opto por:

[string]::Concat("There are ", $count, " items in the list")

Respondido 19 Abr '17, 09:04

esto devuelve System.Object, para tu información. - Barry

Todas estas respuestas parecen muy complicadas. Si está utilizando esto en un script de PowerShell, simplemente puede hacer esto:

$name = 'Slim Shady'
Write-Host 'My name is'$name

Saldrá

Mi nombre es Slim Shady

Observe cómo se pone un espacio entre las palabras para usted

Respondido 12 Jul 15, 19:07

Concatenar cadenas como en los días de DOS. Este es un gran problema para iniciar sesión, así que aquí tienes:

$strDate = Get-Date
$strday = "$($strDate.Year)$($strDate.Month)$($strDate.Day)"

Write-Output "$($strDate.Year)$($strDate.Month)$($strDate.Day)"
Write-Output $strday

Respondido 07 Feb 17, 18:02

Para las fechas, creo que el toString la opcion es mas facil: (Get-Date).toString('yyyyMMdd') - tony

Desde Qué hacer/no hacer en PowerShell: Parte 1:

$id = $assoc.Id
$name = $assoc.Name
$owner = $assoc.owner
"$id - $name - $owner"

respondido 17 mar '22, 00:03

Host de escritura puede concatenar así también:

Write-Host $assoc.Id" - "$assoc.Name" - "$assoc.Owner

Esta es la forma más sencilla, en mi humilde opinión.

Respondido el 17 de junio de 17 a las 13:06

Si está concatenando cadenas para crear rutas de archivo, use el Ruta de unión mando:

Join-Path C:\temp "MyNewFolder"

Agregará automáticamente las barras diagonales finales/iniciales apropiadas para usted, lo que facilita mucho las cosas.

Respondido el 27 de junio de 20 a las 11:06

$assoc = @{
    Id = 34
    FirstName = "John"
    LastName = "Doe"
    Owner = "Wife"
}

$assocId = $assoc.Id
$assocFN = $assoc.FirstName
$assocLN = $assoc.LastName
$assocName = $assocFN, $assocLN -Join " "
$assocOwner = $assoc.Owner

$assocJoin = $assocId, $assocName, $assocOwner -join " - "
$assocJoin
#Output = 34 - John Doe - Wife

Respondido 17 ago 20, 01:08

Personalmente prefiero este estilo:

[string]::Join(' - ', 42, 'Slim Shady', 'Eminem')

o basado en el objeto anterior (desordenado):

[string]::Join(' - ',$assoc.psObject.Properties.value)

Respondido el 06 de enero de 22 a las 17:01

También puede obtener acceso a métodos C#/.NET, y lo siguiente también funciona:

$string1 = "Slim Shady, "
$string2 = "The real slim shady"

$concatString = [System.String]::Concat($string1, $string2)

Output:

Slim Shady, The real slim shady

Respondido 20 Abr '20, 13:04

Solo por diversión. También puede acceder a los valores del PSObject directamente como se muestra a continuación:

$assoc.psobject.Properties.value -join " - "

Pero si no especifica que se debe ordenar el objeto, PowerShell mostrará los valores en un orden aleatorio. Entonces deberías agregar la bandera [ordered]:

$assoc = [pscustomobject] [ordered] @{
    Id = 42
    Name = "Slim Shady"
    Owner = "Eminem"
}

Respondido el 27 de junio de 20 a las 11:06

No veo ninguna razón por la que alguien deba rechazar esta respuesta. +1 de mi parte. - Carsten

Como se señaló en otra parte, puede usar join.

Si está usando comandos como entradas (como yo), use la siguiente sintaxis:

-join($(Command1), "," , $(Command2))

Esto daría como resultado dos salidas separadas por una coma.

Ver https://stackoverflow.com/a/34720515/11012871 para comentarios relacionados

Respondido el 11 de Septiembre de 20 a las 16:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.