如何在PowerShell中连接字符串和变量?


609

假设我有以下代码段:

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

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

我希望这个代码片段显示出来:

42 - Slim Shady - Eminem

但是它显示:

42 + - + Slim Shady + - + Eminem

这使我认为+运算符不适合串联字符串和变量。

如何使用PowerShell处理此问题?


28
如果所有元素都是字符串,并且您将表达式括在括号中,您的代码将起作用: Write-host ($assoc.Id.ToString() + " - " + $assoc.Name + " - " + $assoc.Owner) 此处$ assoc.Id是一个,Int32因此我们必须使用其字符串表示形式。否则,PS尝试执行算术加法而不是级联。
bouvierr

5
考虑到视图的数量,我认为修复该问题的文本是适当的,即使我的编辑对内容进行了相当多的修改。我试图保持问题的术语/措辞和精神完整,同时对其进行足够的改进以使它可以重新打开。
Jeroen 2014年

Answers:


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

请参阅Windows PowerShell语言规范版本3.0,p34,子表达式扩展。


1
该技术也适用于Write-Output et al,因此它可能是工具箱中最有用的一种。
Fenton

4
为什么$($ name)与仅$ name?这是否与使用$ {name}在bash中一样具有防御性?
丹尼·史泰普

73
从技术上讲,这不是串联的。
TravisEz13 2013年

8
@DannyStaple问题已被编辑,以至于答案不再有意义。在一个苗条的示例中,yes "... $name ..."会完全起作用,但是在此答案针对的原始问题中,问题是如何访问对象属性。因此,如果$name.id -eq 42这样"... $name.id ..."将无法按您希望的方式工作,因为它会呈现... @{id=42}.id ...而不是所需的效果。... 42 ...为此,请使用答案的method "... $($name.id) ..."。我将问题添加为书签,以便以后编辑。
杰夫·普基特

3
非常感谢您向我介绍PowerShell语言规范。作为一个初学者,我一直对为什么PowerShell没有随附官方教程感到困惑。该语言规范看起来像我要寻找的。再次感谢!
RayLuo

256

似乎没有人提到单引号和双引号之间的区别。(我正在使用PowerShell 4)。

您可以执行此操作(如@Ben所说):

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

或者您可以这样做:

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

单引号用于文字,请完全像这样输出字符串。双引号用于需要进行一些预处理(例如变量,特殊字符等)的情况

所以:

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

鉴于:

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

http://ss64.com/ps/syntax-esc.html我发现可以作为参考)。


1
也适用于1.0。
史密斯·约翰斯,2016年

134

一种方法是:

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

另一个是:

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

或者只是(但我不喜欢它;)):

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

7
我认为最后一个并不完全符合您的期望。请参阅此处的pastebin。PowerShell的将增加一(即使你有两个在这里)空间到输出之间的空格$assoc.Id"(等)。也就是说,选项1会给您Id__-__Name__-__Owner(每个边的两个空格-),而选项3会给您Id___-___Name___-___Owner三个空格)。
鲁芬2014年

4
也许更有用的pastebin$assoc.Id"###"$assoc.Name 在###的任何一侧添加空格,而"$($assoc.Id)###$($assoc.Name)" 不会
鲁芬2014年

1
第二个让我相信Powershell是我实现目标所需要的-谢谢!
MaVCArt

123

您也可以使用 -join

例如

$name = -join("Jo", "h", "n");

将“ John”分配给$ name。

所以要输出,一行:

Write-Host (-join("Jo", "h", "n"))

68

尝试用括号将要打印的内容包装起来:

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

您的代码被解释为传递给的许多参数Write-Host。将其包装在括号内将串联这些值,然后将结果值作为单个参数传递。


3
+1,我用其他的方法,如当喜欢这种格式Write-DebugWrite-Verbose用于包括双引号和可变值,如Write-Debug ('Running "cmdlet" with parameter $MyVar = ' + $MyVar + " at time " + (Get-Date -DisplayHint Time))
IT熊

是的,这是字符串连接。它不会添加换行符或多余的空格。它使您可以使用单引号或双引号字符串。
LexieHankins '18 -10-24

此技巧是真正的串联,可让您像在.net中一样执行多行字符串。非常适合执行多行SQL语句!为什么Powershell在默认情况下不这样做!?
Brain2000 '18

有很多方法可以做。但这是字符串连接的真正答案。
chingNotCHing

32

另一个选择是:

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

CB建议的“最佳”方法可能是:

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

3
StringBuilder如果您要疯狂,则需要添加该选项。; ^)
ruffin 2014年

2
当然,有一种方法可以将所需的属性传递到外部文件中,然后将它们反序列化为与连字符(?)相连的一连串组件
Code Jockey

很难想象有比这更糟糕的方法了。字符串是不可变的,因此实际上每个串联操作都会产生一个新字符串,并复制原始字符串。
wombatonfire

22

您需要将表达式放在括号中,以防止将它们视为与cmdlet不同的参数:

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

写调试必须这样做
Frank

19

而表达:

"string1" + "string2" + "string3"

将连接字符串。您需要在圆括号前面放置一个$,以使其在传递给powershell命令时作为单个参数求值。例:

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

另外,如果您希望它跨越多行,则需要在行的末尾使用反斜线反引号语法(反引号右侧没有任何空格或字符)。例:

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

(实际上,我认为Powershell的当前实现方式有些错误,因为括号之间不需要多余的引号。如果Microsoft只遵循“ Python”或“ TCL”括号规则,即允许您在开始和开始之间放置尽可能多的换行符,结束括号后,他们将解决人们不喜欢的关于powershell的大多数与行延续和字符串连接有关的问题,我发现有时可以取消括号之间的行延续,但是如果它能奏效的话,它确实是易燃且难处理的。最好添加反引号。)



9

我只想带来另一种使用.NET String.Format的方法

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

2
使用.NET String.Format代替旧的平原有什么优势"{0}" -f $var吗?我看不到在使用.NET代码时普通的PowerShell可以完成这项工作的意义...
Dinei

4
@DineiRockenbach可能不是。只是想提出另一个例子。
马丁·布兰德尔

9

(当前PS版本5.1.17134.407)

我猜到现在所有的事情都说完了,但是到目前为止也可以使用:

$myVar = "Hello"

echo "${myVar} World"

注意:这仅适用于双引号


7

这些答案似乎都很复杂。如果您在PowerShell脚本中使用此功能,则只需执行以下操作:

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

它将输出

我的名字叫Slim Shady

请注意如何在字词之间放置空格



6

连接字符串就像在DOS时代一样。这对于日志记录来说意义重大,因此您可以开始以下操作:

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

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

6

每次我在远离PowerShell后使用PowerShell时,我似乎都在为它(以及许多其他不直观的东西)而苦恼,因此我现在选择:

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

1
这将返回System.Object,fyi。
巴里

3

Write-Host也可以这样连接:

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

这是最简单的方法,恕我直言。


2
$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

2

如果要串联字符串以构建文件路径,请使用join-path命令:

join-path C:\temp "MyNewFolder"

它会自动为您添加适当的尾部/前导斜线,这使事情变得容易得多。

如果这太离题,我深表歉意,但我认为这可能会有所帮助。
如果一段时间不使用PowerShell,有时我会忘记它的存在并开始查找串联运算符。


0

您还可以访问C#/。NET方法,并且以下方法也适用:

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

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

Output:

Slim Shady, The real slim shady

-2

只是为了好玩。您还可以直接访问PSObject的值,如下所示:

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

但是,如果不指定对象的顺序,Powershell将以随机顺序显示值。所以应该添加标志[有序]

$assoc = [pscustomobject] [ordered] @{
    Id = 42
    Name = "Slim Shady"
    Owner = "Eminem"
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.