如何破译文本格式的Powershell语法?

我发现了一个我认为可以适应我的目的的PowerShell脚本 。

它包含格式化输出的这一行:

$largeSizefiles = get-ChildItem -path $filesLocation -include $Extension -recurse -ErrorAction "SilentlyContinue" | ? { $_.GetType().Name -eq "FileInfo" } | where-Object {$_.Length -gt $fileSize} | sort-Object -property length | Select-Object Name, @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}},@{Name="LastWriteTime";Expression={$_.LastWriteTime}},@{Name="Path";Expression={$_.directory}} -first $filesLimit 

关键部分似乎是这样的:

 Select-Object Name, @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}},@{Name="LastWriteTime";Expression={$_.LastWriteTime}},@{Name="Path";Expression={$_.directory}} -first $filesLimit 

我已经阅读了Select-Object上的ss64.com教程,但是我没有find任何解释窗体@ {…..}的expression式如何格式化文本的内容。

@运算符上的ss64.com页面以@(…)的格式显示它,带有parens,而不是大括号。

上面的代码产生以下输出:

 Name : RPI-Image-1-Copy.img Size In MB : 29,477 Path : D:\VirtualDriveShare LastWriteTime : 8/18/2015 6:27:51 PM 

我熟悉一些编程语言,但是这对我来说并不明显,在网上我还没有find明确的解释。 任何人都可以指向我一个很好的教程?

Select-Object可以为每个项目使用Header / Values的哈希表。 在这个例子中:

 Select-Object Name, @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}} ... 

该脚本select名称,然后从“当前pipe道对象的长度”参数派生的“KB中的名称”。

这是进一步格式化,首先将它除以1024然后使用{0:N0}来显示它。

Powershell使用.Netstring格式语法进行显示 – 在这种情况下,{0:N0}转换为:

 // N or n (Number): It represent how many decimal places of zeros to show. String.Format("{0:N4}", pos); //”10.0000″ 

你可能想看一下Kathy Kam的格式101和格式102的文章:

有关string格式的更多细节。

你所缺less的是@{...}表示一个哈希表数组,它由键值对组成。

正如评论中指出的那样, Technet上有这样一篇文章 。 在你的例子中,发生了什么事情是将名称/标题分配给散列表中的键,并将具有格式expression式的variables分配给散列表中的值。

PowerShell中的哈希表非常简单,但如果有帮助, ss64的页面就在这里 ,而Technet也有一个教程页面 。

我同意所有其他的答案,在这种情况下,散列表是一个计算的属性。 我觉得这些内线很棒,但是他们可以以更好的方式呈现出来。 技术仍然是一个单一的,但在不同的规模可读性。

 $largeSizefiles = get-ChildItem ` -path $filesLocation ` -include $Extension ` -recurse ` -ErrorAction "SilentlyContinue" | Where-object { ($_.GetType().Name -eq "FileInfo") ` -and ($_.Length -gt $fileSize)} | sort-Object -property length | Select-Object Name, @{Name="Size In KB";Expression={ "{0:N0}" -f ($_.Length / 1KB)}}, @{Name="LastWriteTime";Expression={$_.LastWriteTime}}, @{Name="Path";Expression={$_.directory}} -first $filesLimit 

如果PoSh期望延续(在或之后),您可以简单地插入一个换行符,当然也可以在连续字符之后插入一个换行符。

@{...=...; ...=...} @{...=...; ...=...}是一个哈希表 。 你可能知道他们是其他语言的“字典”。 这些是键/值对。 分号( ; )将不同的对分隔开,键和值由等号( = )分隔。 请注意,密钥可以隐含引号,使其成为一个string。

{ "{0:N0}" -f ($_.Length / 1KB) }部分是一个脚本块 。 有一堆这些; 哈希表中的所有Expression键映射到一个。 你可以用大括号来说明这一点,而不用在它前面加上前缀。 这些本质上是匿名函数(lambdas)。 $_是pipe道中的当前项目,所以当执行这个脚本块时,它将从pipe道input扩展成单个项目。

特定的脚本块"{0:N0}" -f ($_.Length / 1KB)部分就是使用-f操作符来进行格式化。 这相当于.NET的String.Format ,模式string在左边,模式的参数是在右边的对象数组。 0只是参数索引(所以第一个参数), :N0告诉它格式化为小数点后0位的数字。

现在所有的哈希表之间,我们有一堆逗号。 这些做一个数组 ! 事实certificate,周围的@(...)部分是可选的。

所以我们有一个包含几个string的数组和一串带有NameExpression键的hashtable,而且这个数组是一个传递给Select-Object的参数。 也就是说,这是 – 性质的论据。 请注意SS64文档中的这一行:

要将计算的属性添加到对象,请将散列表指定为-Property参数的值。 哈希表必须包含两个键: 名称expression式与expression式键分配一个脚本块,将确定该属性的值。

所以现在这一切都变得更有意义了。 这只是Select-Object转换input,并且将输出Select-Object的一组“计算”(由脚本块确定)属性和一个“未计算的”(已经存在于传入对象上)属性放在一起。

小调:我相信这个特定的计算属性有些愚蠢:

 @{Name="LastWriteTime";Expression={$_.LastWriteTime}} 

我看不出有什么理由不能像Name那样直接select。