有没有办法将文本文件中的所有 CR 转换为 CRLF?
当我在 Windows 上从 Linux 服务器打开一个文本文件时,所有文本都显示在一行中,但实际上它是多行的。
我想在批处理文件中执行转换。
有人可以建议吗?
有没有办法将文本文件中的所有 CR 转换为 CRLF?
当我在 Windows 上从 Linux 服务器打开一个文本文件时,所有文本都显示在一行中,但实际上它是多行的。
我想在批处理文件中执行转换。
有人可以建议吗?
只要存在不止一种系统和交换数据的冲动,线路分隔符和线路终结器就一直是系统之间兼容性摩擦的根源。Newline 上的维基百科文章对历史背景进行了不错的概述。并且,它针对这个问题提出了多种解决方案,专门用于 Unix 端或 Windows 端。
在 Unix (Linux) 端,查找名为unix2dos
及其近亲的实用程序dos2unix
. 这些都是常见的,可以作为商业 Unix 的一个组件,也可以作为开源工具。如果可用,它们是最好的答案,因为它们(通常,请参阅您的版本的手册页了解详细信息)对意外写入两个行尾的文件非常小心。在那种不幸的情况下,通过这两个实用程序通常会清理文件以保持内部一致。在没有这些方便的命令的情况下,可以使用许多本机实用程序来进行转换。tr
例如,可以使用以下命令将 DOS CRLF 换行符转换为 Unix 换行符:
$ tr -d '\r' < inputfile > outputfile
但请注意,此命令假定所有行都由 CRLF(或 LFCR)终止,并且通过简单地从输入中删除每个 CR 字符来工作。任何裸露的 CR 字符都将丢失。
在 DOS 和 Windows 方面,它曾经很暗淡。的端口unix2dos
并且dos2unix
肯定存在,例如它们包含在更大的 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 inputfile | find /v "" > outputfile
那应该这样做。type
使用参数读取输入文件和管道输出以find
匹配所有行并将它们输出到输出文件。在这个过程中,LF被转换为CRLF
如果我没记错的话,一种可能但相当麻烦的方法是使用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= ||#####################
cat file | perl -pe 's/\R/\n/g'
以下批处理片段可以解决问题:
del outputfile
for /f "delims=" %%x in (inputfile) do echo %%x>>outputfile
它的优点是不依赖于find
程序,这是相当喜怒无常的(在我测试其他解决方案的某些机器上挂起或不起作用)。
在 Windows XP 及更早版本中,您只需在 Dos Edit(或 Windows Edit)中打开并保存文本文件即可将其转换为 CRLF。不幸的是,编辑程序在 Vista 中被删除了。
一种荒谬的方式。适用于以下场景:
在 Notepad++(免费应用程序)中打开文件并设置查看 -> 所有字符。
如果所有行都以 CR 结尾,则:
万一