命令将windows换行符转linux,如何将DOS / Windows换行符(CRLF)转换为Unix换行符(\ n)在Bash脚本中?...

你可以用tr从DOS转换到Unix; 不过,如果CR仅在CRLF字节对的第一个字节中出现在文件中,则只能安全地执行此操作。 这通常是这种情况。 然后你使用:

tr -d '\015' UNIX-file

请注意,名称DOS-file不同于名称UNIX-file ; 如果您尝试使用相同的名称两次,您将最终没有文件中的数据。

你不能这样做(使用标准的“tr”)。

如果您知道如何将回车input脚本( control-V , control-Minputcontrol-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 )并使用它们要utod 。

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 。

这样做与POSIX是棘手的:

POSIX Sed不支持\r或\15 。 即使这样做,就地选项-i不是POSIX

POSIX Awk支持\r和\15 ,但是-i inplace选项不是POSIX

d2u和dos2unix不是POSIX实用程序 ,但ex是

POSIX ex不支持\r , \15 , \n或\12

删除回车:

ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file

要添加回车:

ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file

这个问题可以用标准的工具来解决,但是对于这个粗心大意的陷阱,我build议你安装flip命令,这个命令在20年前被zoo的作者Rahul Dhesi写过。 它在转换文件格式方面做得非常出色,例如,避免了二进制文件的无意破坏,如果您只是围绕改变您所看到的每个CRLF而竞争,那么这有点太简单了。

到目前为止发布的解决scheme只处理部分问题,将DOS / Windows的CRLF转换成Unix的LF; 他们缺less的部分是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

请注意,这将文件的Unix化版本发送到标准输出。 如果你想用Unix化版本replace文件,添加perl的-i标志。

使用AWK你可以这样做:

awk '{ sub("\r$", ""); print }' dos.txt > unix.txt

使用Perl你可以做到:

perl -pe 's/\r$//' < dos.txt > unix.txt

如果您无权访问dos2unix ,但可以阅读此页面,则可以从这里复制/粘贴dos2unix.py 。

#!/usr/bin/env python """\ convert dos linefeeds (crlf) to unix (lf) usage: dos2unix.py """ 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))

跨超级用户发布。

一个更简单的awk解决schemew / o程序:

awk -v ORS='\r\n' '1' unix.txt > dos.txt

技术上'1'是你的程序,B / C awk需要一个给定的选项。

更新 :在长时间第一次重访这个页面之后,我意识到还没有人发布内部解决scheme,所以这里是一个:

while IFS= read -r line; do printf '%s\n' "${line%$'\r'}"; done < dos.txt > unix.txt

这对我有效

tr "\r" "\n" < sampledata.csv > sampledata2.csv

超级容易与PCRE;

作为一个脚本,或用您的文件replace$@ 。

#!/usr/bin/env bash perl -pi -e 's/\r\n/\n/g' -- $@

这将覆盖您的文件!

我build议只做备份(版本控制或其他)

有趣的是,在我的git-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在从input读取行时忽略它们,总是在输出中写入unix行尾。

对于Mac OSX,如果你已经安装了自制软件[ http://brew.sh/%5D [1 ]

brew install dos2unix for csv in *.csv; do dos2unix -c mac ${csv}; done;

确保你已经复制了这些文件,因为这个命令会修改这些文件。 -c mac选项使交换机与osx兼容。

TIMTOWTDI!

perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt

基于@GordonDavisson

必须考虑[noeol]的可能性…

你可以使用awk。 将logging分隔符( RS )设置为匹配所有可能的换行符或字符的正则expression式。 并将输出logging分隔符( ORS )设置为unix样式的换行符。

awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt

作为Jonathan Leffler的Unix to DOS解决scheme的扩展,当您不确定文件的当前行结束时,要安全地转换为DOS:

sed '/^M$/! s/$/^M/'

这将检查该行在转换为CRLF之前还没有在CRLF中结束。

只是想思考同样的问题(在Windows端,但同样适用于Linux)。令人惊讶的是,没有人提到使用良好的旧zip -ll选项(Info-压缩):

zip -ll textfiles-lf.zip files-with-crlf-eol.* unzip textfiles-lf.zip

注:这将创build一个zip文件,保留原始文件名称,但将行结束符转换为LF。 然后, unzip文件将以unzipforms提取,即使用原始名称(但带有LF结尾),从而提示覆盖本地原始文件(如果有)。

相关摘录从zip --help :

zip --help ... -l convert LF to CR LF (-ll CR LF to LF)

有很多的awk / sed / etc的答案作为补充(因为这是这个问题的热门search结果之一):

你可能没有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是输出目录,因此您可以将其replace为当前文件,或者出于安全/备份的原因,将其输出到单独的目录。

我在OSX上试过了sed的'/ 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。 它不是严格的命令行,但它的工作原理,它不抱怨。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值