如何以编程方式(即不使用vi
)将DOS / Windows换行符转换为Unix?
该dos2unix
和unix2dos
命令不可用在某些系统上。如何使用sed
/ awk
/ 这样的命令模拟这些tr
?
如何以编程方式(即不使用vi
)将DOS / Windows换行符转换为Unix?
该dos2unix
和unix2dos
命令不可用在某些系统上。如何使用sed
/ awk
/ 这样的命令模拟这些tr
?
Answers:
您可以tr
用来将DOS转换为Unix。但是,只有当CR仅作为CRLF字节对的第一个字节出现在文件中时,您才能安全地执行此操作。通常是这种情况。然后,您使用:
tr -d '\015' <DOS-file >UNIX-file
请注意,名称与名称DOS-file
不同UNIX-file
;如果尝试两次使用相同的名称,则文件中最终将没有数据。
您不能反过来做(使用标准的“ tr”)。
如果您知道如何输入回车,请返回一个脚本(control-V,control-M输入control-M),然后:
sed 's/^M$//' # DOS to Unix
sed 's/$/^M/' # Unix to DOS
其中“ ^ M”是控制M字符。您还可以使用bash
ANSI-C报价机制指定回车符:
sed $'s/\r$//' # DOS to Unix
sed $'s/$/\r/' # Unix to DOS
但是,如果您将不得不经常执行此操作(粗略地说,不止一次),则安装转换程序(例如dos2unix
和unix2dos
,或者也许dtou
和utod
)并使用它们就更加明智了。
如果需要处理整个目录和子目录,可以使用zip
:
zip -r -ll zipfile.zip somedir/
unzip zipfile.zip
这将创建一个zip存档,其行尾从CRLF更改为CR。unzip
然后将转换后的文件放回原处(并逐个文件询问您-您可以回答:是全部)。感谢@vmsnomad指出了这一点。
tr -d '\015' <DOS-file >UNIX-file
其中DOS-file
== UNIX-file
在一个空文件只是结果。不幸的是,输出文件必须是其他文件。
sed
选项-i
(就地使用)有效;限制是链接文件和符号链接。该sort
命令“始终”(自1979年以来,如果不是更早的话)支持-o
可以列出输入文件之一的选项。但是,这部分是因为sort
必须先读取其所有输入,然后才能写入其任何输出。其他程序偶尔会支持覆盖其输入文件之一。您可以在Kernighan&Pike 的“ UNIX编程环境”中找到通用程序(脚本)来避免问题。
sed -i $'s/\r$//' filename
-在适当位置进行编辑。我正在无法访问互联网的机器上工作,因此软件安装是一个问题。
tr -d "\r" < file
在这里看看使用示例sed
:
# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//' # assumes that all lines end with CR/LF
sed 's/^M$//' # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//' # works on ssed, gsed 3.02.80 or higher
# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\\r`/" # command line under ksh
sed 's/$'"/`echo \\\r`/" # command line under bash
sed "s/$/`echo \\\r`/" # command line under zsh
sed 's/$/\r/' # gsed 3.02.80 or higher
使用sed -i
就地转化例如sed -i 's/..../' file
。
\r
:tr "\r" "\n" < infile > outfile
-d
功能的使用频率更高,在“唯一\r
”情况下无济于事。
\r
的\n
映射具有文件双倍间距的作用;以DOS结尾的每条CRLF行都将成为\n\n
Unix。
使用POSIX这样做很棘手:
POSIX Sed不支持\r
或\15
。即使这样做,就位选项-i
也不是POSIX
POSIX Awk确实支持\r
和\15
,但是该-i inplace
选项不是POSIX
d2u和dos2unix不是POSIX实用程序,但ex是
POSIX前不支持\r
,\15
,\n
或者\12
要删除回车:
ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file
要添加回车符:
ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
tr
支持\r
。 因此,您也可以使用printf '%s\n' '%!tr -d "\r"' x | ex file
(尽管被授予,但\r
即使不是紧接在前面也已删除\n
)。另外,POSIX未指定-b
选项to ex
。
您可以通过选项-c {command}以编程方式使用vim:
对Unix的用法:
vim file.txt -c "set ff=unix" -c ":wq"
Unix下要做的事情:
vim file.txt -c "set ff=dos" -c ":wq"
“ set ff = unix / dos”表示将文件的文件格式(ff)更改为Unix / DOS行尾格式
“:wq”表示将文件写入磁盘并退出编辑器(允许在循环中使用该命令)
vi
都会知道这:wq
意味着什么。对于那些不包含3个字符的字符,则表示1)打开vi命令区域,2)写入和3)退出。
要就地转换文件
dos2unix <filename>
要将转换后的文本输出到其他文件,请使用
dos2unix -n <input-file> <output-file>
您可以使用以下命令在Ubuntu或Debian上安装它
sudo apt install dos2unix
或在MacOS上使用自制软件
brew install dos2unix
可以使用标准工具解决此问题,但是我建议您安装该flip
命令,该陷阱有足够多的陷阱,我建议您安装该命令,该命令由的作者Rahul Dhesi于20年前编写zoo
。它在转换文件格式方面做得非常出色,例如,避免了二进制文件的无意破坏,如果您只是想改变一下看到的每个CRLF,这太容易了。
到目前为止,发布的解决方案仅解决了部分问题,将DOS / Windows的CRLF转换为Unix的LF。他们缺少的部分是DOS使用CRLF作为行分隔符,而Unix使用LF作为行终止符。区别在于,DOS文件(通常)在文件的最后一行之后通常没有任何内容,而Unix则没有。为了正确进行转换,您需要添加最后的LF(除非文件的长度为零,即根本没有行)。我最喜欢的方法(添加一点逻辑来处理Mac样式的CR分隔文件,而不是破坏已经为unix格式的文件)有点perl:
perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt
请注意,这会将文件的Unixified版本发送到stdout。如果要用Unixified版本替换文件,请添加perl的-i
标志。
如果您没有访问dos2unix的权限,但可以阅读此页面,则可以从此处复制/粘贴dos2unix.py。
#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys
if len(sys.argv[1:]) != 2:
sys.exit(__doc__)
content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
content = infile.read()
with open(sys.argv[2], 'wb') as output:
for line in content.splitlines():
outsize += len(line) + 1
output.write(line + '\n')
print("Done. Saved %s bytes." % (len(content)-outsize))
从超级用户交叉发布。
dos2unix
转换所有输入文件。您的用法暗含-n
参数。真正dos2unix
的过滤器是从stdin读取的,如果未提供文件,则写入stdout。
借助PCRE轻松实现超级骗子;
作为脚本,或替换$@
为文件。
#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@
这将覆盖您的文件!
我建议仅使用备份(版本控制或其他方式)进行此操作
--
。我选择此解决方案是因为它很容易理解和适应我。仅供参考,这就是开关的作用:-p
假定“ while input”循环,-i
就地编辑输入文件,-e
执行以下命令
带有程序的更简单的awk解决方案:
awk -v ORS='\r\n' '1' unix.txt > dos.txt
从技术上讲,“ 1”是您的程序,给定选项时,b / c awk需要一个。
更新:在很长一段时间以来第一次重新访问此页面之后,我意识到还没有人发布内部解决方案,所以这里是一个:
while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
awk -v RS='\r\n' '1' dos.txt > unix.txt
awk
或sed
解决方案。另外,您必须使用while IFS= read -r line
来忠实地保留输入行,否则会修剪前导和尾随空格(或者,在read
命令中不使用变量名并使用$REPLY
)。
只是想想同样的问题(在Windows端,但同样适用于Linux。)令人惊讶的是,没有人提到使用非常好的旧zip -ll
选项(Info-ZIP)对文本文件执行CRLF <-> LF转换的非常自动化的方法:
zip -ll textfiles-lf.zip files-with-crlf-eol.*
unzip textfiles-lf.zip
注意:这将创建一个zip文件,保留原始文件名,但将行尾转换为LF。然后unzip
将解压缩后的文件解压缩,即保留其原始名称(但带有LF结尾),从而提示覆盖本地原始文件(如果有)。
相关摘录zip --help
:
zip --help
...
-l convert LF to CR LF (-ll CR LF to LF)
对于Mac osx,如果已安装自制软件[ http://brew.sh/][1]
brew install dos2unix
for csv in *.csv; do dos2unix -c mac ${csv}; done;
确保已复制文件,因为此命令将在适当位置修改文件。-c mac选项使该开关与osx兼容。
-c mac
,这是用于转换OS X之前的CR
仅换行符。您只想将该模式用于Mac OS 9或之前版本的文件。
我尝试在OSX上使用sed's / ^ M $ //'file.txt以及其他几种方法(http://www.thingy-ma-jig.co.uk/blog/25-11-2010/fixing- dos-line-endings或http://hintsforums.macworld.com/archive/index.php/t-125.html)。没有任何效果,文件保持不变(需要使用Ctrl-v Enter来重现^ M)。最后,我使用了TextWrangler。它不是严格的命令行,但是可以正常工作,并且不会抱怨。
dos2unix
使用软件包管理器进行安装,它实际上要简单得多,并且在大多数平台上都存在。