54

我正在对许多服务器运行 PowerShell 脚本,并将输出记录到文本文件中。

我想捕获脚本当前正在运行的服务器。到目前为止,我有:

$file = "\\server\share\file.txt"
$computername = $env:computername

$computername | Add-Content -Path $file

最后一行在输出文件中添加问号。哎呀。

如何将变量输出到 PowerShell 中的文本文件?

4

5 回答 5

81

最简单的 Hello World 示例...

$hello = "Hello World"
$hello | Out-File c:\debug.txt
于 2013-12-15T20:10:00.057 回答
22

注意:下面的答案是从Windows PowerShell的角度编写的。
但是,它也适用于跨平台的PowerShell (Core) v6+除了后者 - 值得称赞的是 -始终默认为无 BOM 的 UTF-8作为字符编码,这是跨平台和跨文化最广泛兼容的字符编码。
.


用更简洁的替代方案和背景信息补充bigtv 的有用答案:

# > $file is effectively the same as | Out-File $file
# Objects are written the same way they display in the console.
# Default character encoding is UTF-16LE (mostly 2 bytes per char.), with BOM.
# Use Out-File -Encoding <name> to change the encoding.
$env:computername > $file

# Set-Content calls .ToString() on each object to output.
# Default character encoding is "ANSI" (culture-specific, single-byte).
# Use Set-Content -Encoding <name> to change the encoding.
# Use Set-Content rather than Add-Content; the latter is for *appending* to a file.
$env:computername | Set-Content $file 

输出到文本文件时,您有2 个使用不同对象表示的基本选择,并且在 Windows PowerShell(与 PowerShell Core相对)中,还使用不同的默认字符编码

  • Out-File(或>)/ Out-File -Append(或>>):

    • 适用于任何类型的输出对象,因为 PowerShell 的默认输出格式应用于输出对象。

      • 换句话说:您得到与打印到控制台时相同的输出
    • 可以通过参数更改的默认编码UTF-16LE,其中大多数字符被编码为2个字节。像 UTF-16LE 这样的 Unicode 编码的优点是它是一个全球字母表,能够编码来自所有人类语言的所有字符。-EncodingUnicode

      • PSv5.1+中,您可以通过偏好变量更改and使用的编码>>>,利用and现在是 and 的有效别名这一$PSDefaultParameterValues事实。例如,要更改为 UTF-8(在 Windows PowerShell 中总是使用BOM),请使用:>>>Out-FileOut-File -Append
        $PSDefaultParameterValues['Out-File:Encoding']='UTF8'
  • Set-Content/ Add-Content:

    • 用于编写已知具有有意义的字符串表示的类型的字符串和实例,例如 .NET 原始数据类型(布尔值、整数等)。

      • .psobject.ToString()在每个输出对象上调用方法,这会导致没有明确实现有意义表示的类型的无意义表示;[hashtable]实例就是一个例子:
        @{ one = 1 } | Set-Content t.txt将文字写入System.Collections.Hashtablet.txt这是@{ one = 1 }.ToString().
    • 可以通过参数更改的默认编码是,它是系统的活动ANSI 代码页,即非 Unicode 应用程序的单字节文化特定的遗留编码,最常见的是Windows-1252。 请注意,文档当前错误地声称 ASCII 是默认编码。-EncodingDefault

    • 请注意,它Add-Content的目的是将内容附加到现有文件,并且仅相当于Set-Content目标文件尚不存在。
      如果文件存在且非空,Add-Content则尝试匹配现有编码。

Out-File///所有行为都对文化敏感>,即Set-Content,如果可用,它们会产生适合当前文化(区域设置)的表示(尽管自定义格式数据可以自由定义其自己的文化不变表示 - 请参阅)。这与 PowerShell 的字符串扩展(双引号字符串中的字符串插值)形成对比,后者是文化不变的- 请参阅我的这个答案Add-Content Get-Help about_format.ps1xml

至于性能:由于Set-Content不必对其输入应用默认格式,因此性能更好。


至于OP的症状Add-Content

由于$env:COMPUTERNAME不能包含非 ASCII 字符(或逐字 ?字符),Add-Content添加到文件中的 ' 不应导致字符?,最可能的解释是?实例是输出文件中预先存在的内容$file的一部分,该内容Add-Content 附加到.

于 2017-05-29T15:53:53.890 回答
11

经过一些试验和错误,我发现

$computername = $env:computername

用于获取计算机名称,但通过Add-Content$computername发送到文件不起作用。

我也试过了$computername.Value

相反,如果我使用

$computername = get-content env:computername

我可以使用将其发送到文本文件

$computername | Out-File $file
于 2013-10-01T18:11:23.803 回答
2

您的示例代码似乎没问题。因此,需要以某种方式挖掘根本问题。让我们消除脚本中出现拼写错误的机会。首先,确保你把Set-Strictmode -Version 2.0你的脚本放在了开头。这将帮助您捕捉拼写错误的变量名。像这样,

# Test.ps1
set-strictmode -version 2.0 # Comment this line and no error will be reported.
$foo = "bar"
set-content -path ./test.txt -value $fo # Error! Should be "$foo"

PS C:\temp> .\test.ps1
The variable '$fo' cannot be retrieved because it has not been set.
At C:\temp\test.ps1:3 char:40
+ set-content -path ./test.txt -value $fo <<<<
    + CategoryInfo          : InvalidOperation: (fo:Token) [], RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined

关于问号的下一部分听起来像你对 Unicode 有问题。像这样使用 Powershell 键入文件时的输出是什么,

$file = "\\server\share\file.txt"
cat $file
于 2013-10-01T18:12:40.537 回答
1

这是一个简单的:

$myVar > "c:\myfilepath\myfilename.myextension"

你也可以试试:

Get-content "c:\someOtherPath\someOtherFile.myextension" > "c:\myfilepath\myfilename.myextension"
于 2020-06-10T19:03:03.840 回答