简体   繁体   English

为什么 [IO.File]::WriteAllText 连接 Get-Content -tail ## output,而 Set-Content 没有?

[英]Why does [IO.File]::WriteAllText concatenate the Get-Content -tail ## output, and Set-Content does not?

If this is a duplicate question for this specific issue, forgive me and please kindly point me in the right direction - I have not seen this in Stack Overflow so far.如果这是针对此特定问题的重复问题,请原谅我并请指出正确的方向 - 到目前为止,我还没有在 Stack Overflow 中看到这一点。

I'm using PowerShell to run a set of commands as follows to find 'NUL' char's in a file.我正在使用PowerShell运行一组命令,如下所示在文件中查找“NUL”字符。 ( -replace works just fine - this is not my problem) -replace工作得很好 - 这不是我的问题)

$findString = '\x00'
$replString = 'DERPS'
$foo = [IO.File]::ReadAllText("C:\SomeFile.txt")
$bar = $foo -replace $findString, $replString
[IO.File]::WriteAllText("C:\SomeFile_2.txt", $bar)
$Lines = Get-Content "C:\SomeFile_2.txt" -tail 10
#I have also used the following with the same effect:
#$Lines = Get-Content "C:\SomeFile_2.txt" |Select-Object -last 10
[IO.File]::WriteAllText("C:\FOOBARRED.txt", $Lines)
Set-Content "C:\NOT_FOOBARRED.txt" $Lines

What I'm experiencing is with [IO.File] it concatenates the last 10 lines into one string:我遇到的是[IO.File]它将最后 10 行连接成一个字符串:

Line 1 of 10 Line 2 of 10 Line 3 of 10 Line 4 of 10 Line 5 of 10 Line 6 of 10 Line 7 of 10 Line 8 of 10 Line 9 of 10 DERPSDERPSDERPSDERPSDERPS

With Set-Content my output looks correct:使用Set-Content我的 output 看起来是正确的:

Line 1 of 10
Line 2 of 10
Line 3 of 10
Line 4 of 10
Line 5 of 10 
Line 6 of 10 
Line 7 of 10
Line 8 of 10
Line 9 of 10
DERPSDERPSDERPSDERPSDERPS

Can anyone explain what the difference is?谁能解释一下有什么区别? Is it correct to assume the "WriteAllText" Command works when it's a raw format, but if it's processed in anyway it will accept the data as one large blob?假设“WriteAllText”命令在其为原始格式时有效,但如果以任何方式对其进行处理,它将接受数据作为一个大 blob 是否正确?

[IO.File]::WriteAllText() expects a single (potentially multiline) string as the argument to its contents parameter. [IO.File]::WriteAllText()需要一个(可能是多行)字符串作为其contents参数的参数。

By contrast, Get-Content -Tail 10 returns an array of strings (when captured in a variable), each containing a line from the file with the trailing newline stripped.相比之下, Get-Content -Tail 10返回一个字符串数组(当在变量中捕获时),每个字符串都包含文件中的一行,并且去掉了尾随的换行符。

PowerShell performs many automatic type conversions, and while they're usually helpful, sometimes they're not: here, it automatically converts the array to a single-line string by concatenating the elements with a single space each [1] , as the following example demonstrates: PowerShell 执行许多自动类型转换,虽然它们通常很有帮助,但有时它们不是:在这里,它通过将每个元素与每个[1]连接起来,自动将数组转换为单行字符串,如下所示示例演示:

PS> "$('line1', 'line2')" # stringify an array
line1 line2  # elements were joined with a space

This automatic stringification of the array stored in $Lines in the context of your [IO.File]::WriteAllText() call caused your problem.在您的[IO.File]::WriteAllText()调用的上下文中存储在$Lines中的数组的这种自动字符串化导致了您的问题。

Therefore, use [IO.File]::WriteAllLines() instead (note: Lines rather than Text ), which expects an array of strings and writes its elements as lines to the file, terminated with a (platform-native) newline each.因此,请改用[IO.File]::WriteAllLines() (注意: Lines而不是Text ),它需要一个字符串数组并将其元素作为行写入文件,每个都以(平台原生)换行符终止。

In other words: It acts like Set-Content when given an array of strings, though note that in Windows PowerShell you'll end up with an ANSI -encoded file by default with Set-Content , whereas .NET - and now PowerShell (Core) 7+ , consistently - default to BOM-less UTF-8. In other words: It acts like Set-Content when given an array of strings, though note that in Windows PowerShell you'll end up with an ANSI -encoded file by default with Set-Content , whereas .NET - and now PowerShell (Core) 7+ ,一致 - 默认为无 BOM 的 UTF-8。


As an aside:作为旁白:

  • A PowerShell alternative to [IO.File]::ReadAllText() is to use Get-Content with the -Raw switch. [IO.File]::ReadAllText()的 PowerShell 替代方法是将Get-Content-Raw开关一起使用。

  • You're already aware of Set-Content as the PowerShell alternative to [IO.File]::WriteAllLines() .您已经知道Set-Content[IO.File]::WriteAllLines()的 PowerShell 替代品。 It can also act as an alternative to [IO.File]::WriteAllText() if you pass it a single, multiline string and also specify the如果您将单个多行字符串[IO.File]::WriteAllText()给它并指定
    -NoNewline switch. -NoNewline开关。


[1] A space character is the default , which you can override via the $OFS preference variable , though that is rarely seen in practice. [1] 空格字符是默认值,您可以通过$OFS首选项变量覆盖它,尽管这在实践中很少见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Get-content 和 [IO.File]::ReadAllText 有什么不同? - What is different between Get-content and [IO.File]::ReadAllText? 设置内容,然后获取内容以某种方式更改内容 - Set-Content and then Get-Content change the content somehow Get-Content和Set-Content用特定的行分开 - Get-Content and Set-Content with specific lines and seperated Powershell获取内容,使用数组进行过滤,然后设置内容 - Powershell Get-Content, filter with ARRAY, and then set-content 为什么在 PowerShell 的 Get-Content、Regex 和 Set-Content 之后所有换行符都消失了? - Why are all newlines gone after PowerShell's Get-Content, Regex, and Set-Content? Powershell:在多个 set-content 和 get-content 操作期间对文件的独占锁定 - Powershell: exclusive lock for a file during multiple set-content and get-content operations 无法在Powershell脚本中使用Get-Content尾部中断 - Does not work break in powershell script with Get-Content tail PowerShell中的“设置内容”是否保留文件访问权限? - Does “Set-Content” in PowerShell keep the File Access rights? 如何在PowerShell v2中匹配和替换Get-Content和Set-Content对象中的字符串? - How to match and replace strings within Get-Content and Set-Content objects in PowerShell v2? POWERSHELL ISE批量/批量选择以进行编码转换(获取内容和设置内容) - POWERSHELL ISE Bulk/Batch select for encoding conversion (Get-Content & Set-Content)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM