【问题标题】:Convert all CR to CRLF in text file using CMD使用 CMD 将文本文件中的所有 CR 转换为 CRLF
【发布时间】:2013-11-11 18:08:35
【问题描述】:

有没有办法将文本文件中的所有 CR 转换为 CRLF?

当我在 Windows 上从 Linux 服务器打开一个文本文件时,所有文本都显示在一行中,但实际上它是多行的。

我想在批处理文件中执行转换。

谁能给点建议?

【问题讨论】:

  • 仅供参考,Linux(以及所有其他 Unix 变体和后代)使用 LF 作为其行终止符(并称其为“换行符”)而不是 CR。然而,旧的 Mac 操作系统确实使用了 CR。 Windows(以及之前的 DOS,以及之前的 CP/M-80,以及许多其他操作系统)将 CR 和 LF 一起用作行终止符。
  • 感谢您的信息,我如何在批处理文件中进行转换,任何帮助
  • 如果文件来自 Linux,那么它应该以 LF 结尾。只有旧 Mac 使用 CR

标签: batch-file cmd newline


【解决方案1】:

只要存在不止一种系统和交换数据的冲动,线路分隔符和线路终结器就一直是系统之间兼容性摩擦的根源。 Wikipedia article on the Newline 对历史背景有一个不错的概述。并且,它针对这个问题提出了多种解决方案,专门用于 Unix 端或 Windows 端。

在 Unix (Linux) 端,查找名为 unix2dos 及其近亲 dos2unix 的实用程序。这些都是常见的,可以作为商业 Unix 的一个组件,也可以作为开源工具。如果可用,它们是最好的答案,因为它们(通常,请参阅您的版本的手册页了解详细信息)对意外写入两个行尾的文件非常小心。在那种不幸的情况下,通过这两个实用程序通常会清理文件以保持内部一致。在没有这些方便的命令的情况下,可以使用许多本机实用程序来进行转换。例如,可以使用tr 命令将 DOS CRLF 换行符转换为 Unix 换行符:

$ tr -d '\r' < inputfile > outputfile

但请注意,此命令假定所有行都由 CRLF(或 LFCR)终止,并且通过简单地从输入中删除每个 CR 字符来工作。任何裸露的 CR 字符都将丢失。

在 DOS 和 Windows 方面,它曾经很暗淡。 unix2dosdos2unix 的端口肯定存在,例如它们包含在更多更大的Cygwin 工具中,这些工具在Windows 机器上提供了完整的unix 仿真。但是很难找到仅使用内置功能的解决方案。

不过,现代 Windows(可能从 Windows XP 开始)更好。在那里,内置的 FIND 命令对行终止符的选择比以前少了很多,并且可以用来进行从 Unix 行结尾到 DOS 结尾的所需转换。上面引用的 Wiki 页面给出了这个秘诀:

C:\...> TYPE filename.u | FIND "" /V >filename.txt

实验表明这也有效,但由于未知原因,它可能不会给出相同的结果:

C:\...> FIND "" /V <filename.u >filename.txt

在这两种情况下,您都会创建一个带有更改的行尾的文件副本。可能不建议更改文件。

我将提到另一种在纸面上看起来总是很诱人的方法。当您使用 Samba 在 Linux 服务器上提供文件系统共享以供 Windows 挂载时,您可以为共享设置一个配置选项,以“文本模式”挂载它。以“文本模式”挂载的共享会自动转换行尾。如果它适合您,那可能是最干净的解决方案。两个系统都使用他们喜欢的文本文件格式,而且都不必大惊小怪。但仔细测试,这个解决方案充满了边缘情况和陷阱。最重要的是,不要期望文本模式文件系统挂载点上的二进制文件能够正确读取。他们经常会,但不一定总是。

【讨论】:

  • TYPE ./public-key.pem | FIND "" /V &gt; p.pem 返回The syntax of the command is incorrect.
【解决方案2】:
type inputfile | find /v "" > outputfile

应该这样做。 type 读取输入文件并将输出通过管道传输到find,并带有参数以匹配所有行并将它们输出到输出文件。在这个过程中,LF被转换为CRLF

【讨论】:

    【解决方案3】:

    如果我没记错的话,一种可能但相当麻烦的方法是使用CertUtil.exe,这是一个自Windows XP 以来本机包含的可执行文件。这是一个可能的脚本(我们称之为conv-eol.bat;查看代码中所有解释性rem 注释):

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    
    rem // Define constants here:
    set "_IFILE=%~1"  & rem // (input file; first command line argument)
    set "_OFILE=%~2"  & rem // (output file; second command line argument)
    set "_IEOL=0d"    & rem // (incoming line-breaks; `0d` or `0a`)
    set "_OEOL=0d 0a" & rem // (outgoing line-breaks; `0d`, `0a`, `0d 0a`, ``)
    set "_TFILE1=%TEMP%\%~n0_%RANDOM%.hex" & rem // (first temporary file)
    set "_TFILE2=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (second temporary file)
    
    rem // Verify input file:
    < "%_IFILE%" rem/ || exit /B
    rem // Convert input file to hexadecimal values (first temporary file):
    CertUtil -f -encodehex "%_IFILE%" "%_TFILE1%" 4 > nul
    rem // Write to second temporary file:
    > "%_TFILE2%" (
        setlocal EnableDelayedExpansion
        rem // Read first temporary file line by line:
        for /F "usebackq delims=" %%L in ("!_TFILE1!") do (
            rem /* Store current line (hex. values), then replace line-breaks
            rem    using the given line-break codes and return result: */
            set "LINE=%%L" & echo(!LINE:%_IEOL%=%_OEOL%!
        )
        endlocal
    )
    rem // Verify output file:
    > "%_OFILE%" rem/ || exit /B
    rem // Convert second temporary file back to text into output file:
    CertUtil -f -decodehex "%_TFILE2%" "%_OFILE%" 4 > nul
    rem // Clean up temporary files:
    del "%_TFILE1%" "%_TFILE2%"
    
    endlocal
    exit /B
    

    将输入文件作为第一个命令行参数,将输出文件作为脚本的第二个参数(它们甚至可能相等):

    conv-eol.bat "input-file.txt" "output-file.txt"
    

    输入和输出换行符必须指定为十六进制字符代码,0d 表示回车 (CR),0a 表示换行 (LF) 字符。

    下表说明了如何在脚本顶部设置变量_IEOL_OEOL,用于不同的换行样式转换任务:

    from       \       to||Mac (CR)             ||Unix/Linux (LF)      ||DOS/Windows (CR+LF)  
    Mac (CR)             ||#####################||_IEOL=0d, _OEOL=0a   ||_IEOL=0d, _OEOL=0d 0a
    Unix/Linux (LF)      ||_IEOL=0a, _OEOL=0d   ||#####################||_IEOL=0a, _OEOL=0d 0a
    DOS/Windows (CR+LF)  ||_IEOL=0a, _OEOL=     ||_IEOL=0d, _OEOL=     ||#####################
    

    【讨论】:

      【解决方案4】:
      cat file | perl -pe 's/\R/\n/g'
      

      【讨论】:

      • 请解释一下你的答案
      • OP 要求提供 Windows CMD 解决方案,而此 unix 解决方案需要两个通常在 Windows 中找不到的程序。
      【解决方案5】:

      以下批处理片段可以解决问题:

      del outputfile
      for /f "delims=" %%x in (inputfile) do echo %%x>>outputfile
      

      它的优点是不依赖于find 程序,该程序相当喜怒无常(在我测试其他解决方案的某些机器上挂起或无法正常工作)。

      【讨论】:

        【解决方案6】:

        在 Windows XP 和更早版本中,您只需在 Dos Edit(或 Windows Edit)中打开并保存文本文件即可将其转换为 CRLF。不幸的是,编辑程序在 Vista 中被删除了。

        【讨论】:

          【解决方案7】:

          一种荒谬的方式。适用于以下场景:

          1. 每行末尾带有 CR 的文本文件。
          2. 文本文件在行尾有一组重复的 CR,后跟一个带有 CRLF 的空行。祝你好运!

          在 Notepad++(免费应用程序)中打开文件并设置查看 -> 所有字符。

          如果所有行都以 CR 结尾,则:

          1. 在 Microsoft Wordpad - NOT - Word 中打开并以 MSDOS 格式保存文件。 ELSE IF 行以 CR 结尾,后跟以 CRLF 结尾的空行,然后
          2. 首先使用 Notepad++ 删除空行。转到编辑 -> 行操作 -> 删除空行并保存文件。
          3. 在 Microsoft Wordpad 中打开文件并以 MSDOS 格式保存。

          如果结束

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-14
            • 1970-01-01
            • 2010-09-06
            • 1970-01-01
            • 2023-02-07
            • 2011-03-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多