对外部程序配管文本附加尾随换行符 [英] Piping Text To An External Program Appends A Trailing Newline
问题描述
Linux终端(CygWin,Bash)对于Windows等)和Windows命令提示符都显示相同的散列,因为PowerShell显示的是不同的散列值。
$ b
tl; dr:
键用于避免 PowerShell的管道 ,以便防止隐含的追加换行符:
- 如果您正在运行您在 Unix 类平台上的命令(使用PowerShell Core ):
sh -cprintf%s'string'| openssl dgst -sha256 -hmac authcode
printf%s
是可移植的替代 echo -n
如果字符串包含'
chars。, double 它们或使用`...`
引用。
- 如果您需要在 Windows 上通过
cmd.exe $ c $因为
cmd.exe
不会直接支持没有尾随换行符的回显:
ul>
cmd / c< NUL set / p =`string`| openssl dgst -sha256 -hmac authcode
请注意,必须存在在 |
之前,为了解决此问题,请参阅本答案。
如果字符串包含非ASCII字符和 你在Windows PowerShell中运行;在这种情况下,首先将 $ OutputEncoding
设置为目标实用程序期望的编码UTF-8: $ OutputEncoding = [Text.Utf8Encoding] :: new()
-
PowerShell,从Windows PowerShell v5.1 / PowerShell Core v6.0.0开始,总是附加尾随换行符当您通过管道将没有任何字符串的字符串发送到外部实用程序时,这是您观察到的差异的原因(即,换行符将会是b ea仅在Unix平台上使用LF,在Windows上使用CRLF序列)。
- 您可以跟踪解决此GitHub问题由OP打开。
$ OutputEncoding
变量中的编码进行转码,该变量默认为 Windows PowerShell,以及PowerShell Core 中的UTF-8编码(在Windows和Unix类平台上)。
- 在PowerShell Core 中,更改为正在讨论,以管理外部程序之间的原始字节流。 那么PowerShell中的
echo -n
会产生一个没有尾随换行符的字符串,因此偶然为了完整起见,这里有一个解释:
-
echo
是别名PowerShell的写入输出
cmdlet,在管道到外部程序的环境中,将文本写入程序的标准输入 next 管道段(类似于Bash / cmd.exe的echo
)。 -
-n
被解释为写入输出
的- 不允许
switch。
-NoEnumerate
仅适用于编写多个对象,因此在此处不起作用。因此,简而言之:在PowerShell中,echo -nstring
与Write-输出-NoEnumeratestring
,因为只输出一个字符串 - 与Write-Out相同放置string
,这反过来与使用string
相同,依靠PowerShell的隐式输出行为。
写入输出
没有选择来抑制尾随的换行符,即使这样做,使用管道传送到 external 程序会将其添加回来。
-
I have been comparing hash values between multiple systems and was surprised to find that PowerShells hash values are different than that of other terminals.
Linux terminals (CygWin, Bash for Windows, etc.) and Windows Command Prompt are all showing the same hash where as PowerShell is showing a different hash value.
This was tested using SHA256 but found the same issue when using other algorithms like md5.
Encoding Update:
Tried changing the PShell encoding but it did not have any effect on the returned hash values.
[Console]::OutputEncoding.BodyName iso-8859-1 [Console]::OutputEncoding = [Text.UTF8Encoding]::UTF8 utf-8
GitHub PowerShell Issue
https://github.com/PowerShell/PowerShell/issues/5974
解决方案tl;dr:
The key is to avoid PowerShell's pipeline in favor of the native shell's, so as to prevent implicit addition of a trailing newline:
- If you're running your command on a Unix-like platform (using PowerShell Core):
sh -c "printf %s 'string' | openssl dgst -sha256 -hmac authcode"
printf %s
is the portable alternative toecho -n
. If the string contains'
chars., double them or use`"...`"
quoting instead.- In case you need to do this on Windows via
cmd.exe
, things get even trickier, becausecmd.exe
doesn't directly support echoing without a trailing newline:
cmd /c "<NUL set /p =`"string`"| openssl dgst -sha256 -hmac authcode"
Note that there must be no space before
|
for this to work. For an explanation and the limitations of this solution, see this answer of mine.Encoding issues would only arise if the string contained non-ASCII characters and you're running in Windows PowerShell; in that event, first set
$OutputEncoding
to the encoding that the target utility expects, typically UTF-8:$OutputEncoding = [Text.Utf8Encoding]::new()
PowerShell, as of Windows PowerShell v5.1 / PowerShell Core v6.0.0, invariably appends a trailing newline when you send a string without one via the pipeline to an external utility, which is the reason for the difference you're observing (that trailing newline will be a LF only on Unix platforms, and a CRLF sequence on Windows).
- You can keep track of efforts to address this problem in this GitHub issue opened by the OP.
Additionally, PowerShell's pipeline is invariably text-based when it comes to piping data to external programs; the internally UTF-16LE-based PowerShell (.NET) strings are transcoded based on the encoding stored in the automatic
$OutputEncoding
variable, which defaults to ASCII-only encoding in Windows PowerShell, and to UTF-8 encoding in PowerShell Core (both on Windows and on Unix-like platforms).- In PowerShell Core, a change is being discussed for piping raw byte streams between external programs.
The fact that
echo -n
in PowerShell does not produce a string without a trailing newline is therefore incidental to your problem; for the sake of completeness, here's an explanation:echo
is an alias for PowerShell'sWrite-Output
cmdlet, which - in the context of piping to external programs - writes text to the standard input of the program in the next pipeline segment (similar to Bash / cmd.exe'secho
).-n
is interpreted as an (unambiguous) abbreviation forWrite-Output
's-NoEnumerate
switch.-NoEnumerate
only applies when writing multiple objects, so it has no effect here.- Therefore, in short: in PowerShell,
echo -n "string"
is the same asWrite-Output -NoEnumerate "string"
, which - because only a single string is output - is the same asWrite-Output "string"
, which, in turn, is the same as just using"string"
, relying on PowerShell's implicit output behavior. Write-Output
has no option to suppress a trailing newline, and even if it did, using a pipeline to pipe to an external program would add it back in.
这篇关于对外部程序配管文本附加尾随换行符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!