如何以编程方式(即不使用vi
)将DOS/Windows换行符转换为Unix?如何在Bash脚本中将DOS/Windows换行符(CRLF)转换为Unix换行符( n)?
dos2unix
和unix2dos
命令在某些系统上不可用。我如何使用像sed
/awk
/tr
这样的命令来模拟这些?
如何以编程方式(即不使用vi
)将DOS/Windows换行符转换为Unix?如何在Bash脚本中将DOS/Windows换行符(CRLF)转换为Unix换行符( n)?
dos2unix
和unix2dos
命令在某些系统上不可用。我如何使用像sed
/awk
/tr
这样的命令来模拟这些?
使用AWK,你可以这样做:
awk '{ sub("\r$", ""); print }' dos.txt > unix.txt
使用Perl,你可以这样做:
perl -pe 's/\r$//' <dos.txt> unix.txt
一个不错的_portable_ awk解决方案。 – mklement0 2015-02-28 05:29:08
您可以使用tr
从DOS到Unix的转换;但是,如果CR仅在CRLF字节对的第一个字节中出现在文件中,则只能安全地执行此操作。这通常是这种情况。然后,可以使用:
tr -d '\015' <DOS-file >UNIX-file
注意名称DOS-file
是从名字UNIX-file
不同;如果您尝试使用两次相同的名称,则最终会在文件中没有数据。
你不能这样做(使用标准'tr')。
如果你知道如何进入回车到一个脚本(控制-V,控制-M进入控制-M),则:
sed 's/^M$//' # DOS to Unix
sed 's/$/^M/' # Unix to DOS
其中 '^ M' 是控制-M字符。您也可以使用bash
ANSI-C Quoting机制,指定回车:
sed $'s/\r$//' # DOS to Unix
sed $'s/$/\r/' # Unix to DOS
但是,如果你将不得不这样做经常(一次以上,粗略地讲),这是更为明智的安装转换程序(例如dos2unix
和unix2dos
,或者可能是dtou
和utod
)并使用它们。
使用'tr -d'\ 015'
@ButtleButkus:恩,是的。这就是为什么我使用了两个不同的名字。如果您在程序全部读取之前切换输入文件,就如同您使用相同名称两次时一样,最终会得到一个空文件。这是类Unix系统中的统一行为。它需要特殊的代码才能安全地处理输入文件的覆盖。按照说明,你会没事的。 – 2013-11-15 01:56:35
我似乎记得文件中的搜索替换功能。 – 2013-11-15 02:08:22
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' – 2010-11-19 00:29:01
@MattTodd你可以发布这个答案吗? '-d'更频繁地被使用,并且在“只有'\ r'”情况下不起作用。 – n611x007 2013-10-14 15:20:52
请注意,建议'\ r'映射为'\ n'具有双重间隔文件的效果;每个在DOS结尾的单个CRLF行在Unix中变成'\ n \ n'。 – 2014-04-30 13:58:31
到目前为止发布的解决方案只处理部分问题,将DOS/Windows的CRLF转换为Unix的LF;他们缺少的部分是DOS使用CRLF作为行分隔符,而Unix使用LF作为行终止符。区别在于DOS文件(通常)在文件的最后一行之后没有任何内容,而Unix将会有。为了正确地进行转换,你需要添加最后的LF(除非文件是零长度,即根本没有行)。我最喜欢这个咒语(一点点添加逻辑来处理的Mac风格的CR-分隔的文件,而不是骚扰文件that're已经是UNIX格式)是位的Perl:
perl -pe 'if (s/\r\n?/\n/g) { $f=1 }; if ($f || ! $m) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt
注意,这将将stdout文件的Unix化版本。如果您想用Unix化版本替换文件,请添加perl的-i
标志。
RIP我的数据文件。在某处出错xD – 2016-01-21 10:53:24
@LudovicZenohateLagouardette它是一个纯文本文件(即csv或tab-demited文本)还是其他?如果它是以某种数据库形式存在的,那么操纵它就好像它是文本一样,这很可能会破坏它的内部结构。 – 2016-01-23 20:53:26
明文csv,但我认为enconding很奇怪。我认为它因此而搞砸了。不过别担心。我总是收集备份,这甚至不是真正的数据集,只有1GB。真实是26GB。 – 2016-01-24 08:02:44
这个问题可以用标准工具来解决,但是对于粗心大意的我有足够多的陷阱,我建议你安装flip
命令,该命令是由作者zoo
的作者Rahul Dhesi在20年前编写的。 它做了出色的工作转换文件格式,同时,例如,避免二进制文件的疏忽造成的破坏,这是一个有点太容易了,如果你只是比赛围绕改变每次你看到CRLF ......
我试图 的sed' s/^ M $ //'file.txt on OSX以及其他几种方法(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的,但可以读取这个页面,那么你可以复制/粘贴在这里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))
交叉发布从superuser。
与POSIX这样做是棘手:
POSIX Sed不支持\r
或\15
。即使这样做了,在地方 选项-i
没有POSIX
POSIX Awk不支持\r
和\15
,但是-i inplace
选项 没有POSIX
D2U和DOS2UNIX的不POSIX utilities,但是ex是
POSIX ex不支持\r
,\15
,\n
或\12
要删除回车:
ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file
要添加回车:
ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
看起来像[POSIX'tr'支持'\ r'。](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tr.html#tag_20_132_13)所以你也可以使用'printf'%s \ n''%!tr -d“\ r”'x | ex文件“(尽管已被授予,即使不是在\ n之前,也删除了\ r)。另外,'ex'的'-b'选项不是由POSIX指定的。 – Wildcard 2017-02-28 01:50:06
对于Mac OSX,如果你有自制软件安装[http://brew.sh/][1]
brew install dos2unix
for csv in *.csv; do dos2unix -c mac ${csv}; done;
请确保您已制作了这些文件的副本,因为此命令将修改这些文件。 -c mac选项使交换机与osx兼容。
'dos2unix'竟然相当方便! – HelloGoodbye 2014-08-21 15:12:11
这个答案真的不是原始海报的问题。 – hlin117 2015-02-07 17:43:10
OS X用户不应该使用'-c mac',它用于转换pre-OS X''CR'-只换行符。您只想将该模式用于Mac OS 9或之前的文件。 – askewchan 2016-04-14 13:20:05
一个更简单的解决方案awk的W/O的程序:
awk -v ORS='\r\n' '1' unix.txt > dos.txt
技术上 '1' 是你的程序,B/C的awk需要一个给定的选项时。
UPDATE: 在很长一段时间重新审视这个页面的第一次后,我意识到,没有一个尚未发布的内部解决方案,所以这里是一个:
while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done <dos.txt> unix.txt
这为我工作
tr "\r" "\n" <sampledata.csv> sampledata2.csv
这会将每个_single_ DOS-newline转换成_two_ UNIX-newlines。 – Melebius 2015-08-04 06:11:35
超级duper容易与PCRE;
作为脚本,或用您的文件替换[email protected]
。
#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- [email protected]
这将覆盖到位您的文件!
我建议只这样做有备份(版本控制或其他方式)
TIMTOWTDI!
perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt
基于@GordonDavisson
一个必须考虑的[noeol]
可能性...
您可以使用AWK。将记录分隔符(RS
)设置为匹配所有可能的换行符或字符的正则表达式。并将输出记录分隔符(ORS
)设置为unix样式的换行符。
awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
这是一个为我工作的(MacOS,'git diff'显示^ M,在vim中编辑) – Dorian 2017-03-01 09:17:44
进行了扩展,乔纳森·莱弗勒的Unix到DOS的解决方案,安全地转换为DOS,当你不能确定该文件的当前行结尾的:
sed '/^M$/! s/$/^M/'
这将检查该行已不在转换为CRLF之前在CRLF中结束。
方才去思考同样的问题 令人惊奇的是没有人提到这样做CRLF <的非常自动化的方式(在Windows的一面,但同样适用于Linux操作系统。) - 用好老zip -ll
选项的文本文件> LF转换(Info-ZIP):
zip -ll textfiles-lf.zip files-with-crlf-eol.*
unzip textfiles-lf.zip
注意:这将创建一个zip文件,保留原始文件名但将行结束符转换为LF。然后unzip
会提取文件作为zip'ed,即与他们的原始名称(但与LF结尾),从而提示覆盖本地原始文件,如果有的话。
从zip --help
相关摘录:
zip --help
...
-l convert LF to CR LF (-ll CR LF to LF)
有趣的是在我的混帐的bash在Windows sed ""
的伎俩已经:
$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text
我的猜测是读取来自输入线时sed的忽略它们并始终在输出上写入unix行尾。
有很多的awk/SED /等答案,从而补充(因为这是这个问题上的搜索结果中的一个):
您可能没有DOS2UNIX的,但你有没有的iconv?
iconv -f UTF-16LE -t UTF-8 [filename.txt]
-f from format type
-t to format type
或者所有目录中的文件:
find . -name "*.sql" -exec iconv -f UTF-16LE -t UTF-8 {} -o ./{} \;
这将运行相同的命令,在当前文件夹中的所有.sql文件。 -o是输出目录,因此您可以将其替换为当前文件,或者出于安全/备份原因,将其输出到单独的目录。
如果你可以编译到目标系统上,你可以试试https://github.com/mdolidon/endlines;它的制作非常便携。 – 2014-09-03 10:17:32
通常,只需使用软件包管理器来安装'dos2unix',它确实简单得多,而且在大多数平台上都存在。 – 2015-10-20 20:15:43