请注意以下简短的场景(这是在PowerShell中):
PS> git diff -U3 -r -M HEAD -- .\Metadata\LegacyTypeModules\xyz.Web.Main.draft.json | Out-File -Encoding ascii c:\temp\1.diff
PS> git apply --cached C:\temp\1.diff
error: patch failed: Metadata/LegacyTypeModules/xyz.Web.Main.draft.json:69
error: Metadata/LegacyTypeModules/xyz.Web.Main.draft.json: patch does not apply
这会失败,因为文件中的最后一行不是以CRLF结尾:
然而,在bash中运行时,同样的命令也可以工作:
$ git diff -U3 -r -M HEAD -- Metadata/LegacyTypeModules/xyz.Web.Main.draft.json > /c/Temp/2.diff
$ git apply --cached /c/Temp/2.diff
P11F70F@L-R910LPKW MINGW64 /c/xyz/tip (arch/1064933)
这两个补丁之间的区别是:
所以问题似乎发生了,因为Powershell用CRLF终止了通过管道的每一行,而bash保留了原始的行结尾。
我理解为什么会发生这种情况- Powershell操作对象,对象是字符串不包括EOL字符。当写入文件时,Powershell将对象转换为字符串(对于字符串,转换是nop),并使用默认的EOL序列来分隔行。
这是否意味着Powershell不能在EOL敏感的场景中使用?
3条答案
按热度按时间polhcujo1#
的确:
[Console]::OutputEncoding
)。Out-File
这样的文件输出小程序在写入目标文件时总是使用 platform-native 换行符序列(Windows上的CRLF)来终止每个(字符串化的)输入对象(使用 * 它的 * 默认字符编码(或通过-Encoding
指定的编码),这在技术上与用于 * 解码 * 外部程序输出的编码无关)。换句话说:
在 Windows PowerShell 和PowerShell (Core) * 以及v7.3.x 中,*PowerShell管道(和重定向) 不 * 支持通过传递 * 原始二进制数据 *。
>
而不是Out-File
**才能从外部程序(如git
)捕获原始字节输出,就像在Bash中一样。v7.3的解决方法-:
"
n")连接并终止解码后的输出行,并将结果多行字符串按原样(
-NoNewLine`)写入目标文件,如zdan's helpful answer所示。cmd.exe /c
,因为**cmd.exe
的管道和重定向 * 是 * 原始字节管道**:请注意,这里使用了一个here-string,以提高可读性,并便于任何嵌入式引用(此处不适用)。
jucafojl2#
您可以尝试使用
join
将CRLF替换为unix EOL:ymdaylpp3#
标准的diff(也称为patch)以LF行结尾来终止行。这是因为这是POSIX为
diff
的输出指定的。所有行必须包含LF行结尾。当CR在修补程序中位于LF之前时,它被视为要修补的内容的一部分。因此,在您的情况下,补丁可能不适用,因为旧的内容被列为具有CRLF行结尾,而它没有。
不幸的是,PowerShell在这方面完全崩溃了,它的管道破坏了通过它们的数据。这对于任何类型的二进制数据都是如此。如果你正在使用任何一种设计用于在Unix上运行的工具,比如Git,你需要避免使用PowerShell的管道。