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

Posted

技术标签:

【中文标题】如何在 PowerShell 中连接字符串和变量?【英文标题】:How do I concatenate strings and variables in PowerShell? 【发布时间】:2013-02-13 08:06:54 【问题描述】:

假设我有以下sn-p:

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


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

我希望这个 sn-p 会显示:

42 - Slim Shady - Eminem

但它却显示:

42 + - + Slim Shady + - + Eminem

这让我觉得+ 运算符不适合连接字符串和变量。

您应该如何使用 PowerShell 来解决这个问题?

【问题讨论】:

您的代码有效 if 所有元素都是字符串,并且您将表达式括在括号中:Write-host ($assoc.Id.ToString() + " - " + $assoc.Name + " - " + $assoc.Owner) 这里 $assoc.Id 是 Int32 所以我们必须使用它字符串表示。否则 PS 会尝试执行算术加法而不是串联。 考虑到浏览量,我认为修复这个问题的文本是合适的,尽管我的编辑改变了很多内容。我试图保持问题的术语/措辞和精神完好无损,同时对其进行了足够的改进,以便可以重新打开它。 【参考方案1】:
Write-Host "$($assoc.Id) - $($assoc.Name) - $($assoc.Owner)"

参见Windows PowerShell Language Specification Version 3.0, p34, 子表达式扩展。

【讨论】:

为什么是 $($name) 而不是 $name?这与使用 $name 的 bash 中的防御方式相同吗? 这不是技术上的串联。 @DannyStaple 这个问题有很多been edited,以至于答案不再有意义。在苗条的阴暗示例中,是的 "... $name ..." 将完全一样,但是在此答案所针对的原始问题中,问题是如何访问对象属性。所以如果$name.id -eq 42 那么"... $name.id ..." 不会像你想要的那样工作,因为它会像... @id=42.id ... 而不是所需的... 42 ... 那样呈现为此,请使用答案的方法"... $($name.id) ..."。我正在为问题添加书签以便稍后编辑。 非常感谢您向我指出 PowerShell 语言规范。作为一个初学者,我一直对为什么 PowerShell 没有附带官方教程感到困惑。这个语言规范看起来像我正在寻找的。再次感谢! 这不适用于跨多行分布字符串。请改用( $string1, $string2, $string3 ) -join ""($string1 + $string2 + $string3)。使用这些方法,您可以在字符串之间使用空格(空格、制表符和换行符),但请确保 (1) 每个字符串在同一行后面都有一个逗号/空格,(2) 使用反引号字符 ` 在您的代码之间的任何空行的末尾,以及 (3) 如果您使用 -join,则结束括号和 -join 运算符必须在同一行【参考方案2】:

单引号和双引号是有区别的。 (我使用的是 PowerShell 4)。

你可以这样做(Benjamin said):

$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

(我觉得 How-to: Escape characters, Delimiters and Quotes 很有参考价值)。

【讨论】:

也适用于 1.0。 此引用规则和连接演示适用于 'nix shell 脚本(例如 Bash),除了 PowerShell。仅便携性因素就赢得了我的投票。 我很惭愧地说我的脚本是用 "" 调试的,但是用 '' 编写带有字符串和变量的命令,这是几个小时的工作,这个答案是为了找出我做错了什么。难以置信! powershell 很简洁,会在Write-Host 'My name is'$name中的字符串和变量内容之间放置一个空格【参考方案3】:

你也可以使用-join

例如

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

将“Hello world”分配给 $var。

所以要在一行中输出:

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

【讨论】:

至少这个可以用在foreach中 请补充,如果您使用命令作为输入,请将命令包装在 $() 中.....例如... -join($(cmd1), ",", $(cmd2 )) ...我花了太长时间才弄清楚,因为我是 powershell 的新手 @S.Melted 为什么要包裹在 $() 里面? 经过进一步审查,我的需要只需要()。例如:-join("Timestamp: ", Get-Date) 给出错误,而-join("Timestamp: ", (Get-Date)) 运行正常。但是,this 解释了何时需要$() Write-Host -join("Hello", " ", "world") 不会加入,因为整个 join 参数需要括号,包括 arg = join 的名称。【参考方案4】:

一种方法是:

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

【讨论】:

我不认为最后一个完全符合您的预期。见pastebin here。 Powershell 将为$assoc.Id" (等)之间的空白添加一个(即使您在这里有两个)空间。也就是说,选项 1 为您提供 Id__-__Name__-__Owner(每个 - 的每侧两个空格),但选项 3 提供 Id___-___Name___-___Owner三个 个空格)。 Perhaps a more useful pastebin。 $assoc.Id"###"$assoc.Name 在 ### 的任一侧添加空格,而 "$($assoc.Id)###$($assoc.Name)" 不会【参考方案5】:

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

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

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

【讨论】:

+1,当使用Write-DebugWrite-Verbose等其他方法来包含双引号和变量值时,我更喜欢这种格式,例如Write-Debug ('Running "cmdlet" with parameter $MyVar = ' + $MyVar + " at time " + (Get-Date -DisplayHint Time)) 是的,这是字符串连接。它不会添加换行符或额外的空格。它允许您使用单引号或双引号字符串。 这个技巧是真正的连接,允许你做多行字符串,就像你在 .net 中一样。非常适合做多行 SQL 语句!为什么powershell默认不这样做!? 有很多方法可以做。但这是字符串连接的真正答案。 非常感谢!我很难为 Invoke-WebRequest 构建 URI 参数,而您的解决方案是唯一有效的解决方案:Invoke-WebRequest -uri ('http://mysvr/guestauth/app/rest/...'+$param1+'_'+$param2+'_something,count:10')【参考方案6】:

另一种选择是:

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

“最佳”方法可能是 C.B. 建议的一种:

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

【讨论】:

如果你想继续疯狂,你需要添加StringBuilder 选项。 ;^) 肯定有一种方法可以将所需的属性通过管道传输到外部文件中,然后将它们反序列化为用连字符(?)连接的组件字符串 很难想象比这更糟糕的方法。字符串是不可变的,因此每个连接操作实际上都会产生一个新字符串,复制原始字符串的字符。 响应 Code Jockey 使用 += 可能每次都会产生一个新的字符串,但是对于一个相对较小的字符串添加额外的小字符串,谁在乎呢。清楚正在发生的事情是最重要的,而 PowerShell 让事情正常运行比其他任何事情都更重要。【参考方案7】:

while 表达式:

"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 的大多数与行继续和字符串连接相关的问题。

我发现你有时可以在括号之间的行继续上去掉反引号,但它是否会起作用真的很不稳定且不可预测......最好只添加反引号。)

【讨论】:

【参考方案8】:

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

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

【讨论】:

Write-Debug 是强制的【参考方案9】:

这是另一种替代方法:

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

【讨论】:

【参考方案10】:

(当前 PowerShell 版本 5.1.17134.407)

这也适用于现在:

$myVar = "Hello"

echo "$myVar World"

注意:这只适用于双引号

【讨论】:

【参考方案11】:

我只是想用另一种方式来使用 .NET String.Format:

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

【讨论】:

使用 .NET String.Format 代替旧的普通 "0" -f $var 有什么好处吗?我没有看到使用 .NET 代码的意义,而普通的 PowerShell 可以完成这项工作...... @DieiRockenbach 可能不会。只是想举一个例子。【参考方案12】:

每次使用 PowerShell 后,我似乎都在为这个(以及许多其他不直观的事情)而苦恼,所以我现在选择:

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

【讨论】:

这会返回 System.Object,仅供参考。【参考方案13】:

这些答案看起来都很复杂。如果您在 PowerShell 脚本中使用它,您可以简单地执行以下操作:

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

会输出

我的名字是斯利姆·谢迪

注意单词之间的空格是如何给你的

【讨论】:

【参考方案14】:

来自What To Do / Not to Do in PowerShell: Part 1

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

【讨论】:

【参考方案15】:

就像在 DOS 时代一样连接字符串。这对于日志记录来说是一件大事,所以你去吧:

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

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

【讨论】:

对于日期,我认为toString 选项更简单:(Get-Date).toString('yyyyMMdd')【参考方案16】:

Write-Host 也可以这样连接:

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

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

【讨论】:

【参考方案17】:

如果您要连接字符串来构建文件路径,请使用Join-Path 命令:

Join-Path C:\temp "MyNewFolder"

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

【讨论】:

【参考方案18】:
$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

【讨论】:

【参考方案19】:

您还可以访问 C#/.NET 方法,以下方法也可以使用:

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

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

Output:

Slim Shady, The real slim shady

【讨论】:

【参考方案20】:

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

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

但是如果你没有指定对象应该是有序的,PowerShell 会以随机顺序显示这些值。所以你应该添加标志[ordered]

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

【讨论】:

我看不出有人应该否决这个答案的任何理由。来自我的 +1。【参考方案21】:

如其他地方所述,您可以使用 join。

如果您使用命令作为输入(就像我一样),请使用以下语法:

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

这将导致两个输出用逗号分隔。

相关评论见https://***.com/a/34720515/11012871

【讨论】:

【参考方案22】:

我个人比较喜欢这种风格:

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

或基于上述(无序)对象:

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

【讨论】:

以上是关于如何在 PowerShell 中连接字符串和变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在powershell中将变量放入文件名

Powershell中变量的定义和使用

如何在powershell的变量中执行字符串

在 Powershell 中,如何通过提供名称作为 $var 来设置环境变量?

如何在 Azure DevOps 的 Powershell 内联脚本中正确连接字符串?

如何使用XML文件中的PowerShell更新数据源连接字符串