Powershell在回显到文件时生成未知字符

yzxexxkh  于 2023-02-23  发布在  Shell
关注(0)|答案(4)|浏览(134)

我正在尝试使用Powershell将3行纯文本回显到文件中:

echo "#Generated" > psftp.scp
echo "put test.txt" >> psftp.scp
echo "quit" >> psftp.scp

然后,我使用psftp.exe批处理模式运行该文件(在SFTP中执行命令),但psftp错误地看到一个无效字符:

psftp: unknown command " ■#"

我错过了什么?我可以在Windows记事本中手动键入文件,它(PSFTP)可以工作。无论我将第一行更改为(X1 M0 N1 X),它都会得到这个错误,第一部分中有块符号。
我试过在记事本++ w/“显示所有符号”中查看该文件,但只在行尾看到CR & LF,这是正常的。

zpgglvta

zpgglvta1#

尝试使用set/add-content而不是redirection。您可能还需要设置编码。

"#Generated" | set-content psftp.scp -Encoding Ascii
"put test.txt" | add-content psftp.scp -Encoding Ascii
"quit" | add-content psftp.scp -Encoding Ascii
iih3973s

iih3973s2#

和Out-File一样,Powershell 5中“〉”和“〉〉”的默认编码是UTF 16 LE(“Unicode”)。我猜psftp读不懂这个?“FF FE”是编码签名或“BOM”。你是如何运行psftp的?

format-hex psftp.scp

           Path: C:\Users\me\psftp.scp

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   FF FE 23 00 47 00 65 00 6E 00 65 00 72 00 61 00  .þ#.G.e.n.e.r.a.
00000010   74 00 65 00 64 00 0D 00 0A 00 70 00 75 00 74 00  t.e.d.....p.u.t.
00000020   20 00 74 00 65 00 73 00 74 00 2E 00 74 00 78 00   .t.e.s.t...t.x.
00000030   74 00 0D 00 0A 00 71 00 75 00 69 00 74 00 0D 00  t.....q.u.i.t...
00000040   0A 00                                            ..

在powershell 5.1中设置“〉"、“〉〉”和out-file的默认编码:

$PSDefaultParameterValues = @{'Out-File:Encoding' = 'Ascii'}
8yparm6h

8yparm6h3#

在我的例子中,我将一个.cmd文件中的.ps1管道传输到powershell中

type script.ps1 | powershell -ExecutionPolicy Bypass

尽管以其他方式运行脚本时没有错误,但以这种方式运行时,由于无效字符,它会在第一行(注解行)抛出语法错误。
我发现如果我用wScite编辑器保存. ps1文件,默认值是“UTF-8 with BOM”,我将其更改为“UTF-8”,之后将脚本管道传输到PowerShell就可以正常工作了。

dhxwm5r4

dhxwm5r44#

许多年后,一种系统概述的尝试:

  • 在现代的跨平台**PowerShell (Core)版本(v6及更高版本)中,现在可以使用>>>,因为它们现在创建*无BOM的UTF-8***文件(就像 * 所有 * 文件写入cmdlet现在 * 一致 * 做的那样)。
  • 考虑到许多现代程序都需要这种字符编码,您的代码可能会按原样工作
  • 如果需要不同的编码,请使用-Encoding调用cmdlet,如下所述。
  • 在传统的*Windows PowerShell*版本(其最新和最终版本是v5.1)中,>>>默认为UTF-16LE(PowerShell错误地将其称为Unicode),很少有外部程序理解这一点,这是问题的原因。[1]
  • >>>实际上是Out-FileOut-File -Append的别名,指定 different 编码需要使用-Encoding参数显式调用它们。
  • 但是,对于 string 输入,您可以使用Set-ContentAdd-Content,它们默认Default,表示系统的活动ANSI代码页,例如美国英语系统上的Windows-1252
# `-Encoding Default` implied.
# OK with ASCII-only characters, otherwise only if the program
# expects ANSI encoding.
# If you use -Encoding ASCII, any non-ASCII characters become
# *literal ?* chars., i.e. information is *lost*.
# (That can also happen for `-Encoding Default` for Unicode chars.
# outside the character set of the active ANSI code page.)
'#Generated' | Set-Content psftp.scp
'put test.txt' | Add-Content psftp.scp
'quit' | Add-Content psftp.scp

如果您想要 * 无BOM的UTF-8,这就有点棘手了,因为Windows PowerShell的cmdlet * 不 * 支持创建此类文件--Encoding utf8总是创建 * 带有 * BOM的文件(不像在 PowerShell(Core) 中,相反地,您必须使用-Encoding utf8bom来显式地请求BOM)。奇怪的是,New-Item * 确实 * 创建了无BOM的UTF-8文件,因此它可以用于创建文件,这允许后续的Add-Content调用安全地使用-Encoding utf8,因为它们不会将BOM添加到 existing 文件内容中。

# New-Item, curiously, creates BOM-less UTF-8 files.
# The string must be passed via -Value (or as a *single* pipeline input), 
# and a trailing newline must be added explicitly.
$null = New-Item -Force psftp.scp -Value "#Génerated`n"
'put test.txt' | Add-Content -Encoding utf8 psftp.scp
'quit' | Add-Content -Encoding utf8 psftp.scp

[1]PowerShell创建的UTF-16 LE文件 * 总是 * 有一个BOM (Byte Order Mark,它是2字节序列0xFF0xFE,字符/代理对的一半表示为 *16位代码单元 *,即 * 两个 * 字节,ASCII范围字符的0x0NUL)作为其2字节序列中的第二个字节。

相关问题