为什么Powershell重定向>>会更改文本内容的格式?

时间:2019-07-09 01:34:09

标签: powershell io-redirection

我想使用重定向附加>>或write>来写入txt文件,但是当我这样做时,会收到奇怪的格式“ \ x00a \ x00p ...” 。 / p>

我成功使用了set-content和add-content,为什么它们能按预期运行,而不是>>和>重定向运算符?

使用Powershell'cat'以及简单的python打印显示输出。

rocket_brain> new-item test.txt
rocket_brain> "appended using add-content" | add-content test.txt
rocket_brain> cat test.txt

 appended using add-content

但是如果我使用重定向附加>>

rocket_brain> "appended using redirect" >> test.txt
rocket_brain> cat test.txt

 appended using add-content
 a p p e n d e d   u s i n g   r e d i r e c t

简单的python脚本:read_test.py

with open("test.txt", "r") as file:   # open test.txt in readmode
    data = file.readlines()           # append each line to the list data
    print(data)                       # output list with each input line as an item

使用read_test.py,我发现格式有所不同

rocket_brain> python read_test.txt
 ['appended using add-content\n', 'a\x00p\x00p\x00e\x00n\x00d\x00e\x00d\x00 \x00u\x00s\x00i\x00n\x00g\x00 \x00r\x00e\x00d\x00i\x00r\x00e\x00c\x00t\x00\r\x00\n', '\x00']

注意:如果我仅使用重定向附加>>(或写>)而没有先使用add-content,则cat输出看起来很正常(而不是间隔开),但是我将得到 / x00p < / i>使用python脚本时,每一行的格式(包括以>运算符开头的所有add-content命令)。在记事本(或VS等)中打开文件,文本始终看起来像预期的那样。在cmd(而不是PS)中使用>>或>也会以预期的ascii格式存储文本。

相关链接cmd redirection operators,  PS redirection operators

3 个答案:

答案 0 :(得分:6)

注意:问题最终是在 Windows PowerShell 中,不同的cmdlet /运算符使用了不同的默认编码。此问题已在PowerShell Core 中得以解决,在该环境中,始终使用无BOM的UTF-8。


  • >>在附加到现有文件时盲目应用Out-File的默认编码(实际上,>的行为类似于{{1} }和Out-File(如>>),它们在 Windows PowerShell 中是名为 Out-File -Append的编码,即UTF-16LE ,其中大多数字符被编码为2个字节的序列,即使是在ASCII范围内的序列也是如此;后者的高字节为Unicode0x0)。

    • 因此,除非目标文件的现有内容使用相同的编码,否则最终将得到不同编码的 mix ,这就是您所遇到的情况。 [1]
  • 与此相反,NUL确实尝试检测文件的现有编码。再次感谢js2010,您在 empty上使用了它文件,在这种情况下,将应用 Add-Content的默认编码,在 Windows PowerShell 中,该编码为 {{1} } ,它是指系统的活动ANSI代码页

    • 因此,要在附加更多内容时匹配Set-Content调用最初创建的单字节ANSI编码,请使用Default而不是Add-Content,或简单地继续使用Out-File -Append -Encoding Default

      • 或者,使用>>选择其他编码,并在Add-Content调用中进行匹配; UTF-8通常是最佳选择,不过请注意,当您在Windows PowerShell中创建UTF-8文件时,它将以BOM表(将文件标识为UTF-8的伪字节顺序标记)开头,类似于Unix平台通常不期望)。

      • 在PowerShell v5.1 +中,您还可以全局更改默认编码,包括Add-Content -Encoding ...Out-File -Append的默认编码(在早期版本中是不可能的) )。例如,要更改为UTF-8,请使用:
        >


(在Windows PowerShell中)除了使用不同的默认编码外,重要的是请注意一方面 >> / $PSDefaultParameterValues['*:Encoding']='UTF8'Set-Content / Add-Content / >非字符串输入的行为完全不同:

简而言之:前者将简单的>>格式应用于输入对象,而后者则执行与控制台相同的输出格式-有关详细信息,请参见this answer


[1]由于Out-File [-Append]设置的初始内容,Windows PowerShell将文件解释为ANSI编码(没有BOM时的默认设置),其中每个字节都是其自己的字符。因此,后面附加的UTF-16内容也将被解释为ANSI,因此.ToString()字节本身就被视为字符,并像空格一样打印到控制台。

答案 1 :(得分:1)

SplitPipelineActionBlock>>重定向控制台输出。因此,我认为有时还会包含一些奇怪的字符。 >>>> cmdlet密切相关。

Out-File不会将控制台输出转发到文件,它只会写入您提供的值(例如变量或管道对象)

about_redirection

答案 2 :(得分:1)

默认情况下,

>>或out-file -append将追加unicode文本,即使该文件最初不是unicode。添加内容将首先检查文件的编码,然后进行匹配。添加内容或设置内容也默认为ansi编码。我永远不会使用>,>>或文件外。

看到东西之间有空格是一种统一的礼物。 Unicode通常在每个字母之间都有$ nulls。如果转储十六进制,例如在emacs esc-x hexl-mode中,则可以看到它。 Boms是文件开头的2或3个十六进制字符。

var data=[
  {material_id:1, item:'test'},
  {material_id:1,  item:'test2'},
  {material_id:2,  item:'test2'},
]
let res = [...new Set(data.map(x => x.material_id))]
console.log(res)

这是一个正确构造的unicode文本文件,是从emacs十六进制模式复制和粘贴的。 fffe是宝。每个字符之后是00。最后是0d和0a,回车和换行。这样的东西使我感兴趣。某些Windows实用程序可能会创建没有bom的unicode文本文件(icacls / save)。然后,如果您键入文件,则字母之间似乎会有空格。

a p p e n d e d   u s i n g   r e d i r e c t