我正在对许多服务器运行 PowerShell 脚本,并将输出记录到文本文件中。
我想捕获脚本当前正在运行的服务器。到目前为止,我有:
$file = "\\server\share\file.txt"
$computername = $env:computername
$computername | Add-Content -Path $file
最后一行在输出文件中添加问号。哎呀。
如何将变量输出到 PowerShell 中的文本文件?
我正在对许多服务器运行 PowerShell 脚本,并将输出记录到文本文件中。
我想捕获脚本当前正在运行的服务器。到目前为止,我有:
$file = "\\server\share\file.txt"
$computername = $env:computername
$computername | Add-Content -Path $file
最后一行在输出文件中添加问号。哎呀。
如何将变量输出到 PowerShell 中的文本文件?
最简单的 Hello World 示例...
$hello = "Hello World"
$hello | Out-File c:\debug.txt
注意:下面的答案是从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 编码的优点是它是一个全球字母表,能够编码来自所有人类语言的所有字符。-Encoding
Unicode
>
>>
,利用and现在是 and 的有效别名这一$PSDefaultParameterValues
事实。例如,要更改为 UTF-8(在 Windows PowerShell 中总是使用BOM),请使用:>
>>
Out-File
Out-File -Append
$PSDefaultParameterValues['Out-File:Encoding']='UTF8'
用于编写已知具有有意义的字符串表示的类型的字符串和实例,例如 .NET 原始数据类型(布尔值、整数等)。
.psobject.ToString()
在每个输出对象上调用方法,这会导致没有明确实现有意义表示的类型的无意义表示;[hashtable]
实例就是一个例子:@{ one = 1 } | Set-Content t.txt
将文字写入System.Collections.Hashtable
,t.txt
这是@{ one = 1 }.ToString()
.可以通过参数更改的默认编码是,它是系统的活动ANSI 代码页,即非 Unicode 应用程序的单字节文化特定的遗留编码,最常见的是Windows-1252。
请注意,文档当前错误地声称 ASCII 是默认编码。-Encoding
Default
请注意,它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
附加到.
经过一些试验和错误,我发现
$computername = $env:computername
用于获取计算机名称,但通过Add-Content$computername
发送到文件不起作用。
我也试过了$computername.Value
。
相反,如果我使用
$computername = get-content env:computername
我可以使用将其发送到文本文件
$computername | Out-File $file
您的示例代码似乎没问题。因此,需要以某种方式挖掘根本问题。让我们消除脚本中出现拼写错误的机会。首先,确保你把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
这是一个简单的:
$myVar > "c:\myfilepath\myfilename.myextension"
你也可以试试:
Get-content "c:\someOtherPath\someOtherFile.myextension" > "c:\myfilepath\myfilename.myextension"