Powershell 哈希表未按预期写入文件 - 仅接收“System.Collections”行

发布于 2024-11-06 10:05:09 字数 1252 浏览 0 评论 0原文

有人可以解释为什么我的第一个示例不起作用,以及为什么添加 ForEach-Object 可以解决问题?提前致谢!


我将命令的返回解析为哈希表(帖子末尾的示例),并希望将信息记录到文件中作为处理的一部分。我知道 $ht.GetEnumerator() | Sort-Object Name 将返回完整的哈希值到屏幕,并进行排序。但是,一旦我尝试将内容发送到文件,它就会崩溃。

$ht | Add-Content log.txt

仅记录 System.Collections.Hashtable 的单行。因此,我也尝试过

$ht.GetEnumerator() | Sort-Object Name | Add-Content log.txt 

并最终得到了几行

System.Collections.DictionaryEntry
System.Collections.DictionaryEntry
System.Collections.DictionaryEntry

,然后我尝试循环遍历并单独处理每个行

foreach ($key in $ht.keys) {
Add-Content log.txt "$key : $ht.$key" }

,并最终得到

Server address : System.Collections.Hashtable.Server address
Client address : System.Collections.Hashtable.Client address
User name : System.Collections.Hashtable.User name

已解决

$ht.GetEnumerator() | Sort-Object Name |
ForEach-Object {"{0} : {1}" -f $_.Name,$_.Value} |
Add-Content log.txt 

作为参考,哈希表示例:

$ht = @{
    "Server address" = "server.net";
    "Client address" = "10.20.121.153";
    "User name" = "myuser"
}

Can someone please explain Why my first examples don't work, and why adding in a ForEach-Object solves the problem? Thanks in advance!


I parsed the return from a command into a hashtable (sample at end of post) and want to log the information to a file as part of my processing. I know that $ht.GetEnumerator() | Sort-Object Name will return the full hash to screen, sorted. However, once I try sending things to file, it breaks.

$ht | Add-Content log.txt

only logs a single row of System.Collections.Hashtable. So, I've also tried

$ht.GetEnumerator() | Sort-Object Name | Add-Content log.txt 

and end up with rows of

System.Collections.DictionaryEntry
System.Collections.DictionaryEntry
System.Collections.DictionaryEntry

So then I tried to loop through and handle each individually with

foreach ($key in $ht.keys) {
Add-Content log.txt "$key : $ht.$key" }

and end up with

Server address : System.Collections.Hashtable.Server address
Client address : System.Collections.Hashtable.Client address
User name : System.Collections.Hashtable.User name

Solved with:

$ht.GetEnumerator() | Sort-Object Name |
ForEach-Object {"{0} : {1}" -f $_.Name,$_.Value} |
Add-Content log.txt 

For reference, the hashtable sample:

$ht = @{
    "Server address" = "server.net";
    "Client address" = "10.20.121.153";
    "User name" = "myuser"
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

听风吹 2024-11-13 10:05:09

回答 为什么 部分,您显然有一个解决方案:)

在第一个示例中,

$ht | Add-Content log.txt

PowerShell 采用 $ht 并尝试以某种方式将其转换为字符串,以便可以通过存储添加内容。由于没有为哈希表定义转换,因此转换仅返回类型名称。与 new-Object Random|Add-Content d:\log.txt 示例相同。同样,只写入类型名称。

接下来

$ht.GetEnumerator() | Sort-Object Name | Add-Content log.txt 

也是类似的。 GetEnumerator 返回用于迭代的对象;返回 System.Collections.DictionaryEntry 类型的对象。同样,没有转换为字符串,因此返回类型名称。

就我个人而言,我认为 PowerShell 应该足够智能并且可以提供帮助。问题是“如何?”。设计人员可能不想对输出进行硬编码。它可能是 "{key}: {value}""{key} = {value}""{key}/{value}",或...格式不清楚,因此他们将其留给我们来决定和格式化,就像您使用 foreach 语句所做的那样。

Answering the why part, you obviously have a solution :)

In your first example

$ht | Add-Content log.txt

PowerShell takes $ht and tries to somehow convert it to a string so that it can be stored via Add-Content. Because there is no conversion defined for the hashtable, only the type name is returned from the conversion. Same as for example new-Object Random|Add-Content d:\log.txt. Again, only type name is written.

Next

$ht.GetEnumerator() | Sort-Object Name | Add-Content log.txt 

is similar. GetEnumerator returns object that is used for iteration; objects of type System.Collections.DictionaryEntry are returned. Again, there is no conversion to string, so type names are returned.

Personally, I think PowerShell should be smart enough and help here. The question is "how?". Designers probably didn't want to hardcode the output. It might be "{key}: {value}" or "{key} = {value}", or "{key}/{value}", or ... The format is not clear, so they left it for us to decide and format as you did it with the foreach statement.

倚栏听风 2024-11-13 10:05:09

我同意 mjolinor 的观点...只是没有足够的积分来投票...另外我会补充一点,你不需要 GetEnumerator

$ht | out-string | add-content log.txt

就可以做到这一点。

I agree with mjolinor... just not enough points to vote up... plus i'll add that you dont need the GetEnumerator

$ht | out-string | add-content log.txt

will do it.

一城柳絮吹成雪 2024-11-13 10:05:09

您的第一个示例不起作用,或者更好的是,部分起作用,因为您正在尝试获取字符串中的属性值。通常,在字符串内部,解析器只能解析直接变量(如 $key)。要解析更复杂的变量,您需要括号。

对于循环,这应该有效:

foreach ($key in $ht.keys) {
Add-Content log.txt "$key : $($ht.$key)" }

或者甚至更好

$ht.keys | %{ Add-Content log.txt "$_ : $($ht.$_)" }

Your first example does not work, or better, partially works, because you are trying to get a property value within the string. Normally, inside strings, the parser is able to resolve only direct variables (like $key). To resolve more complex variable you need parenthesis.

For the loop, this should work:

foreach ($key in $ht.keys) {
Add-Content log.txt "$key : $($ht.$key)" }

or even better

$ht.keys | %{ Add-Content log.txt "$_ : $($ht.$_)" }
挥剑断情 2024-11-13 10:05:09

正如您在 Microsoft 文档中所看到的,哈希表只是名称/值对的集合。

所以 $ht 实际上是由 System.Collections.DictionaryEntry 组成的 System.Collections.Hashtable

使用它的一个好方法是

foreach ($i in $ht.keys)
{
  add-content log.txt ("{0} {1}" -f $i, $ht[$i])
}

As you can see in Microsoft documentation a hash table is simply a collection of name-value pairs.

So $ht is really System.Collections.Hashtable composed of System.Collections.DictionaryEntry.

A good way to use it is

foreach ($i in $ht.keys)
{
  add-content log.txt ("{0} {1}" -f $i, $ht[$i])
}
找回味觉 2024-11-13 10:05:09

怎么样:

 $ht.GetEnumerator() | Sort-Object Name | out-string | Add-Content log.txt 

How about:

 $ht.GetEnumerator() | Sort-Object Name | out-string | Add-Content log.txt 
允世 2024-11-13 10:05:09

您可以使用 Out-File 将哈希表的“原始”转储写入 ASCII 文件:

$data = @{
  Name = "Something"
  Type = "123"
}
$data | Out-File "myfile.txt" -Encoding ascii

You can write a "raw" dump of a hash table to an ASCII file using Out-File:

$data = @{
  Name = "Something"
  Type = "123"
}
$data | Out-File "myfile.txt" -Encoding ascii
べ繥欢鉨o。 2024-11-13 10:05:09

Microsoft 建议在迭代密钥之前先克隆密钥!

这是从 https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-hashtable?view=powershell-7.4

$environments.Keys.Clone() | ForEach-Object {
    $environments[$_] = 'SrvDev03'
}

所以在你的情况下它应该看起来像:

foreach ($key in $ht.keys.Clone()) {
   Add-Content log.txt "$key : $ht.$key" 
}

Microsoft recommends to take a clone of the keys before iterating over them!

This is copy/paste from https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-hashtable?view=powershell-7.4

$environments.Keys.Clone() | ForEach-Object {
    $environments[$_] = 'SrvDev03'
}

So in your case it should look like :

foreach ($key in $ht.keys.Clone()) {
   Add-Content log.txt "$key : $ht.$key" 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文