假设我有以下片段:
$assoc = New-Object PSObject -Property @{
Id = 42
Name = "Slim Shady"
Owner = "Eminem"
}
Write-Host $assoc.Id + " - " + $assoc.Name + " - " + $assoc.Owner
我希望这个片段显示:
42 - Slim Shady - 阿姆
但相反,它显示:
42 + - + Slim Shady + - + 阿姆
这让我认为 +
运算符不适合连接字符串和变量。
你应该如何使用 PowerShell 来解决这个问题?
Write-host ($assoc.Id.ToString() + " - " + $assoc.Name + " - " + $assoc.Owner)
这里 $assoc.Id 是一个 Int32
,所以我们必须使用它的字符串表示。否则 PS 会尝试执行算术加法而不是串联。
Write-Host "$($assoc.Id) - $($assoc.Name) - $($assoc.Owner)"
请参阅 Windows PowerShell Language Specification Version 3.0, p34, 子表达式扩展。
单引号和双引号是有区别的。 (我使用的是 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 非常适合参考)。
powershell
很简洁,会在字符串和 Write-Host 'My name is'$name
中的变量内容之间放置一个空格
您也可以使用 -join
例如
$var = -join("Hello", " ", "world");
将“Hello world”分配给 $var。
所以要输出,在一行中:
Write-Host (-join("Hello", " ", "world"))
$()
内?
()
。例如:-join("Timestamp: ", Get-Date)
给出错误,而 -join("Timestamp: ", (Get-Date))
运行正常。但是,this 解释了何时需要 $()
。
Write-Host -join("Hello", " ", "world")
不会加入,因为整个 join
参数需要括号,包括 arg = join 的名称。
一种方法是:
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
$assoc.Id
和 "
之间的空格(等)的输出添加一个(即使您在这里有两个)空间。也就是说,选项 1 为您提供 Id__-__Name__-__Owner
(每个 -
的每一侧有两个空格),但选项 3 提供 Id___-___Name___-___Owner
(三个 个空格)。
$assoc.Id"###"$assoc.Name
将在 ### 的任一侧添加空格,而 "$($assoc.Id)###$($assoc.Name)"
不会。
尝试将要打印的任何内容包装在括号中:
Write-Host ($assoc.Id + " - " + $assoc.Name + " - " + $assoc.Owner)
您的代码被解释为传递给 Write-Host
的许多参数。将其包裹在括号内将连接这些值,然后将结果值作为单个参数传递。
Write-Debug
或 Write-Verbose
等其他方法来包含双引号和变量值时,我更喜欢这种格式,例如 Write-Debug ('Running "cmdlet" with parameter $MyVar = ' + $MyVar + " at time " + (Get-Date -DisplayHint Time))
Invoke-WebRequest -uri ('http://mysvr/guestauth/app/rest/...'+$param1+'_'+$param2+'_something,count:10')
另一种选择是:
$string = $assoc.ID
$string += " - "
$string += $assoc.Name
$string += " - "
$string += $assoc.Owner
Write-Host $string
“最佳”方法可能是 CB 建议的一种:
Write-Host "$($assoc.Id) - $($assoc.Name) - $($assoc.Owner)"
StringBuilder
选项。 ;^)
虽然表达:
"string1" + "string2" + "string3"
将连接字符串,您需要在括号前面放一个 $ 以使其在传递给 PowerShell 命令时作为单个参数进行评估。例子:
Write-Host $( "string1" + "string2" + "string3" )
作为奖励,如果您希望它跨越多行,那么您需要在行尾使用笨拙的反引号语法(反引号右侧没有任何空格或字符)。
例子:
Write-Host $(`
"The rain in " +`
"Spain falls mainly " +`
"in the plains" )`
-ForegroundColor Yellow
(实际上,我认为 PowerShell 目前的实现有点错误,因为它需要括号之间不必要的反引号。如果微软只是遵循 Python 或 Tcl 括号规则,允许您在开始和结束之间放置任意数量的换行符括号那么他们将解决人们不喜欢的大多数与行延续和字符串连接相关的 PowerShell 问题。
我发现您有时可以在括号之间的行继续上保留反引号,但是如果它会起作用,它真的很不稳定且不可预测......最好只添加反引号。)
您需要将表达式放在括号中,以防止它们被视为 cmdlet 的不同参数:
Write-Host ($assoc.Id + " - " + $assoc.Name + " - " + $assoc.Owner)
(当前 PowerShell 版本 5.1.17134.407)
这也适用于现在:
$myVar = "Hello"
echo "${myVar} World"
注意:这只适用于双引号
这是另一种方法:
Write-Host (" {0} - {1} - {2}" -f $assoc.Id, $assoc.Name, $assoc.Owner)
我只想使用 .NET String.Format 带来另一种方法:
$name = "Slim Shady"
Write-Host ([string]::Format("My name is {0}", $name))
String.Format
而不是旧的普通 "{0}" -f $var
有什么好处吗?我没有看到使用 .NET 代码的意义,而普通的 PowerShell 可以完成这项工作......
每次使用 PowerShell 后,我似乎都在为这个(以及许多其他不直观的事情)而苦苦挣扎,所以我现在选择:
[string]::Concat("There are ", $count, " items in the list")
这些答案似乎都很复杂。如果您在 PowerShell 脚本中使用它,您可以简单地执行以下操作:
$name = 'Slim Shady'
Write-Host 'My name is'$name
它会输出
我的名字是苗条的阴影
请注意如何在您的单词之间放置空格
就像在 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')
来自 What To Do / Not to Do in PowerShell: Part 1:
$id = $assoc.Id
$name = $assoc.Name
$owner = $assoc.owner
"$id - $name - $owner"
$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
个人比较喜欢这种风格:
[string]::Join(' - ', 42, 'Slim Shady', 'Eminem')
或基于上述(无序)对象:
[string]::Join(' - ',$assoc.psObject.Properties.value)
您还可以访问 C#/.NET 方法,以下内容也可以使用:
$string1 = "Slim Shady, "
$string2 = "The real slim shady"
$concatString = [System.String]::Concat($string1, $string2)
Output:
Slim Shady, The real slim shady
只是为了好玩。您还可以直接访问 PSObject 的值,如下所示:
$assoc.psobject.Properties.value -join " - "
但是,如果您没有指定对象应该是有序的,PowerShell 将以随机顺序显示这些值。所以你应该添加标志 [ordered]
:
$assoc = [pscustomobject] [ordered] @{
Id = 42
Name = "Slim Shady"
Owner = "Eminem"
}
如其他地方所述,您可以使用 join。
如果您使用命令作为输入(就像我一样),请使用以下语法:
-join($(Command1), "," , $(Command2))
这将导致两个输出用逗号分隔。
有关相关评论,请参见 https://stackoverflow.com/a/34720515/11012871
"... $name ..."
将完全一样,但在此答案解决的原始问题中,问题是如何访问对象属性。因此,如果$name.id -eq 42
则"... $name.id ..."
不会像您想要的那样工作,因为它会呈现为... @{id=42}.id ...
而不是所需的... 42 ...
为此,请使用答案的方法"... $($name.id) ..."
。我正在为问题添加书签以供稍后编辑。( $string1, $string2, $string3 ) -join ""
或($string1 + $string2 + $string3)
。使用这些方法,您可以在字符串之间使用空格(空格、制表符和换行符),但请确保 (1) 每个字符串在同一行后面都有一个逗号/空格,(2) 使用反引号字符 ` 在代码之间的任何空行的末尾,以及 (3) 如果您使用-join
,则结束括号和-join
运算符必须在同一行