【问题标题】:How to prevent \n to from being translated to \r\n on Windows如何在Windows上重新转换为\ r \ n
【发布时间】:2018-02-18 04:31:15
【问题描述】:

我正在使用 Windows 10 和草莓 Perl

众所周知,Linux 中的行终止符是\n,而Windows 中是\r\n

我发现,在我的电脑上,Linux类型的文件在进行类似替换操作后会自动转换为windows类型\r\n

perl -i.bak -pe "s/aaa/bbb/g" test.txt

但这不是我想要的,而且似乎不合理。我想知道这是 Strawberry Perl 问题还是其他因素?

如何让行终止符在 Windows 上不受影响?

【问题讨论】:

  • “但这不是我想要的,而且似乎不合理” 为什么你认为 perl 假设它应该在一个操作系统上读写标准 Windows 文件是不合理的? Windows 系统,除非你另有说明?
  • 嗨,@Borodin。因为 perl 隐含地做了一些事情,我认为在 windows 上使用 \n 专门作为换行符没有任何问题。实际上,我将 unix 格式设置为 notepad++ 默认值,这是我的主编辑器。这对我来说很重要,因为我同时在 windows 桌面和 linux 服务器上工作。
  • "你能举个例子,\n 会导致 windows 程序出现问题吗?" 这完全取决于每个应用程序是如何编写的,你必须在上面测试所有内容Windows 以确保它在数据中没有 CR 字符的情况下正常工作。可能的影响是程序将在文件中找不到行终止符,因此会将整个内容作为单个记录读取。我知道记事本将无法正确读取文件,并且可能还有许多其他示例。这将根据应用程序产生许多影响,但大多数事情根本不起作用。
  • “我实际上并没有在 Windows 上使用太多命令行” 那么听起来你真的无法分支并使用非Windows 上的标准文件格式。我建议你应该等到你对系统更加熟悉后再做出如此极端的决定。
  • 也许您需要在 Stack Overflow 上提出一个问题:“在 Windows 系统上将我的所有文件保存为 Linux 格式有什么问题吗?”。您还应该阅读Do not change Linux files using Windows apps and tools

标签: windows perl line


【解决方案1】:

这是 Perl 在 Windows 上的标准行为(将 \n 转换为 \r\n)。

您可以使用binmode 绕过它,这会阻止 Perl 进行自动行结束转换。

然后您的命令将被更改为如下所示。它告诉binmode 写入STDOUT,然后必须将输出重定向到另一个文件。下面的命令应该做你想做的事(虽然没有到位):

perl -pe "BEGIN{ binmode(STDOUT) } s/aaa/bbb/g" test.txt > newtest.txt

【讨论】:

  • 你好,birryree。非常感谢您的回答。但解决方案听起来很复杂。我忘了问为什么 perl 强制换行符在 windows 上 \r\n ?这没有意义,我提供给 perl 的命令与换行操作无关,它只是为我做了不必要的事情。顺便说一句,如何进行就地更换?我发现 -i.bak 不起作用。
  • @user15964 这是一种在 Windows 上显示的 Perl 行为。基本上,在 Windows 上写入文件时,Perl 会将 \n 转换为 \r\n,除非您使用 binmode 并按照我在答案中显示的操作。您不必显式地执行任何操作来进行自动换行符转换。使用binmode 进行操作是我不知道该怎么做的(而且我没有设置正在运行的 Windows,所以我无法测试我在那里所做的任何事情是否正确)。
  • @Borodin,我对 birryree 的回答做了一个小的更正,然后问了一个关于 Perl 是如何实现的问题,看看这在多大程度上是第 3 方行为(即基于 Microsoft 的 C 运行时文本模式,它Python 2 也使用) vs 专门选择的行为。对于后者,我根据自己的经验举了一个例子,Python 3 决定默认在 Windows 上将换行符转换为 CRLF,即使它不再使用 CRT 的文本模式。
  • @Borodin 感谢您的编辑和建议 - 我删除了 Powershell 部分,因为它可能有点令人困惑和不必要。
  • ... C11 WG14 草案中的脚注 271 明确允许实现支持 mode 字符串中的其他字符。我不确定这可以追溯到多远,但我认为它一直是被允许的。当然,b 选项被明确列出,没有它,实现被明确允许执行字符转换(第 7.12.2.2 段)。
【解决方案2】:

“实际上,我将 unix 格式设置为 notepad++ 默认值,这是我的主编辑器” 我认为您应该努力为适当的系统保留具有正确行尾的文件。如果您将 Linux 文件保存在任何地方,您将不会交到任何朋友,因为这会让其他人很难使用您的非标准方法

正确使用两个系统并不难,因为您所要做的就是在从一个系统复制到另一个系统时自动进行更改。您可以在制作副本时使用 dos2unixunix2dos,但是编写一个 Perl 程序以使用相关版本的文本文件更新您的所有系统是一项简单的工作

但是,如果你坚持这个计划,这应该可以帮助你实现它

默认情况下,在 Windows 上运行时,perl 将使用 IO 层 :unix:crlf,这意味着它与在 Linux 系统上的工作方式相同,但在输入时将 CRLF 转换为 LF,在输入时将 LF 转换为 CRLF输出

您可以通过添加显式伪层:raw 来使单个open 调用表现不同,这会删除:crlf 层。但是如果你想修改特殊文件句柄STDINSTDOUTARGV,那么你需要一个不同的策略,因为这些句柄是由 perl 为你打开的

您可以在程序顶部使用open pragma,像这样

use open IO => ':raw';

这将隐式地将:raw 层应用于每个输入或输出文件句柄,包括特殊句柄。您可以使用

从命令行进行设置
perl -Mopen=IO,raw program.pl

或者你可以设置PERLIO环境变量

set PERLIO=raw

这将影响以后从同一个 cmd 窗口运行的每个程序

【讨论】:

  • 嗨,鲍罗丁。非常感谢您的回答和各种建议。但我只是尝试了perl -Mopen=IO,raw -i.bak -pe "s/aaa/bbb/g" test.txtset PERLIO=raw && perl -i.bak -pe "s/ibrav/lll/g" 0.txt。但他们没有工作,结果文件也变成了'\r\n'。
猜你喜欢
  • 2014-02-19
  • 1970-01-01
  • 2023-01-24
  • 1970-01-01
  • 1970-01-01
  • 2018-01-02
  • 2011-12-21
  • 2011-02-07
相关资源
最近更新 更多