我有以下powershell:
# Find all .csproj files
$csProjFiles = get-childitem ./ -include *.csproj -recurse
# Remove the packages.config include from the csproj files.
$csProjFiles | foreach ($_) {(get-content $_) |
select-string -pattern '<None Include="packages.config" />' -notmatch |
Out-File $_ -force}
似乎工作正常。运行后,packages.config中的行不在文件中。
但是在我运行之后,该文件的 TOP 还有一个额外的换行符。 (不是底部。)
我很困惑如何到达那里。 如何摆脱文件顶部生成的额外换行符?
更新:
我换了一种不同的做法:
$csProjFiles | foreach ($_) {$currentFile = $_; (get-content $_) |
Where-Object {$_ -notmatch '<None Include="packages.config" />'} |
Set-Content $currentFile -force}
它工作正常,并且文件顶部没有额外的行。但我不介意为什么最好的例子是添加额外的行。
答案 0 :(得分:4)
Out-File
和重定向操作符>
/ >>
获取任意输入对象并将其转换为字符串表示形式控制台 - 即 PowerShell 默认输出格式已应用 - 并将这些字符串表示形式发送到输出文件。
这些字符串表示通常具有可读性的前导和/或尾随新行 。
Get-Help about_Format.ps1xml
了解详情。 Set-Content
适用于输入对象 已经是字符串或应该被视为字符串 < /强>
.psobject.ToString()
以获取字符串表示形式,在大多数情况下,该表示形式遵循基础.NET类型的.ToString()
方法。结果表示通常不相同,了解何时选择哪个cmdlet /运算符非常重要。
此外,默认字符编码不同:
Out-File
和>
/ >>
默认为UTF-16 LE ,PowerShell在可选Unicode
的上下文中调用-Encoding
1}}参数。 Set-Content
默认使用您系统的遗产&#34; ANSI&#34;代码页(单字节,扩展ASCII代码页),PowerShell调用Default
。
要更改编码:
Ad-hoc 更改:将 -Encoding
参数与Out-File
或{{1}一起使用明确控制输出字符编码
您无法更改Set-Content
/ >
ad-hoc 使用的编码,但请参见下文。
[PSv3 +] 更改默认 (谨慎使用):使用>>
机制(请参阅{ {3}}),可以为参数设置默认值:
更改$PSDefaultParameterValues
的默认编码也会更改PSv5.1或更高版本中的Out-File
/ >
[2] 。
例如,要将其更改为UTF-8,请使用:
>>
$PSDefaultParameterValues['Out-File:Encoding']='UTF8'
和>
使用的内容。 如果您更改>>
的默认设置,请务必将其更改为Set-Content
:
Add-Content
您还可以使用通配符模式表示要应用默认参数值的cmdlet /高级函数名称;例如,如果您使用$PSDefaultParameterValues['Set-Content:Encoding'] = $PSDefaultParameterValues['Add-Content:Encoding'] ='UTF8'
,则具有$PSDefaultParameterValues['*:Encoding']='UTF8'
参数的所有 cmdlet将默认为该值,但这是不明智的,因为在某些cmdlet中{ {1}}指的是输入编码。
cmdlet之间没有单个共享前缀,用于写入允许定位所有输出 cmdlet 的文件,但是您可以为每个动词定义一个模式:
-Encoding
警告:-Encoding
在全局范围内定义,因此您对其所做的任何修改都会全局生效 ,并影响后续命令
要限制对脚本/函数范围及其后代范围的更改,请使用本地 $enc = 'UTF8; $PSDefaultParameterValues += @{ 'Out-*:Encoding'=$enc; 'Set-*:Encoding'=$enc; 'Add-*:Encoding'=$enc; 'Export-*:Encoding'=$enc }
变量,您可以将其初始化为空哈希表从头开始($PSDefaultParameterValues
),或初始化为全局值的克隆($PSDefaultParameterValues
)
在目前的情况下,输出对象是由$PSDefaultParameterValues = @{}
输出的$PSDefaultParameterValues = $PSDefaultParameterValues.Clone()
个实例:
使用默认格式,与[Microsoft.PowerShell.Commands.MatchInfo]
一样,它们在上方输出一个空行,下面有两个空行(多个实例在单个块之间的连续块中打印上面和下面的空行集。
如果你在Select-String
上调用Out-File
,它们只评估匹配的行(没有原始路径前缀,因为输入是通过管道而不是通过.psobject.ToString()
/ Set-File
参数)作为文件名,没有前导或尾随空行。
也就是说,如果您将-Path
或-LiteralPath
显式输出为字符串,那么您只需将| Select-Object -ExpandProperty Line
或| ForEach-Object Line
显示为Out-File
或Set-Content
1}}会产生相同的结果(默认编码除外)。
PS:LotPing的观察是正确的:您似乎将foreach
声明与ForEach-Object
cmdlet 混淆了(其中令人遗憾的是,内置别名foreach
也会出现这种情况,导致混淆。)
Get-Help about_Parameters_DefaultValues
并不需要$_
的明确定义:在您传递给它的(隐含的-Process
)脚本块中,$_
是自动定义为手头的输入对象。
($_)
foreach
的{{1}}参数有效忽略:因为它评估为ForEach-Object
:自动变量{{1} },当在特殊上下文之外使用时 - 例如管道中的脚本块 - 有效地评估为$null
,并且将$_
放在它周围没有区别,所以你&#39 ;有效地传递$null
,这是被忽略的。
[1]验证(...)
不默认值如下:$null
在en-US系统上产生ASCII
,这是'0x{0:x}' -f $('ä' | Set-Content t.txt; $b=[System.IO.File]::ReadAllBytes("$PWD\t.txt")[0]; ri t.txt; $b)
的Windows-1252代码点(与Unicode代码点重合,但输出是一个没有BOM的单字节编码文件)。
如果您明确使用0xe4
,则会获得ä
literal -Encoding ASCII
的代码点,因为那是使用0x3f
转换的内容所有非ASCII字符。至。
功能
[2] PetSerAl发现ForEach-Object
cmdlet显示?
的{{1}}和ASCII
有效别名,>
指出重新定义>>
因此也重新定义了Out-File [-Append]
/ Out-File
;同样,>
通过>>
指定默认编码也会对$PSDefaultParameterValues
/ Out-File
生效。
Windows PowerShell v5.1是以这种方式工作的最低版本..
向source-code location寻求帮助的提示。