33

在字段中间(不是行尾)有一些带有不正确放置换行符的分隔文件,在 Vim 中显示为 ^M。它们源自 MSSQL 数据库的 freebcp(在 Centos 6 上)导出。以十六进制转储数据显示 \r\n 模式:

$ xxd test.txt | grep 0d0a
0000190: 3932 3139 322d 3239 3836 0d0a 0d0a 7c43

我可以用 awk 删除它们,但不能用 sed 做同样的事情。

这适用于 awk,完全删除换行符:

awk 'gsub(/\r/,""){printf $0;next}{print}'

但这在 sed 中没有,而是保留了换行符:

sed -i 's/\r//g'

这似乎没有效果:

sed -i 's/\r\n//g'

在 sed 表达式 (ctrl+v, ctrl+m) 中使用 ^M 似乎也不起作用。

对于这类任务,sed 更容易理解,但我正在努力学习更多关于这两者的知识。我使用 sed 是否不当,还是有限制?

4

4 回答 4

53

您可以使用命令行工具dos2unix

dos2unix input

或者使用tr命令:

tr -d '\r' <input >output

实际上,您可以进行文件格式切换vim

方法一:
:e ++ff=dos
:w ++ff=unix
:e!
方法B:
:e ++ff=dos
:set ff=unix
:w

编辑

如果要删除\r\n文件中的序列,请尝试以下命令vim

:e ++ff=unix           " <-- make sure open with UNIX format
:%s/\r\n//g            " <-- remove all \r\n
:w                     " <-- save file

您的awk解决方案工作正常。另外两个sed解决方案:

sed '1h;1!H;$!d;${g;s/\r\n//g}' input
sed ':A;/\r$/{N;bA};s/\r\n//g' input
于 2012-07-27T03:05:20.967 回答
23

我相信某些版本的sed将无法识别\r为字符。但是,您可以使用一项bash功能来解决该限制:

echo $string | sed $'s/\r//'

在这里,您让'\r' 替换为构造bash中的实际回车符,然后将其作为命令传递给它。(假设您使用; 其他 shell 应该有类似的结构。)$'...'sedbash

于 2012-07-27T03:04:51.273 回答
10

sed -e 's/\r//g' input_file

这对我有用。-e-i命令的区别。

我还提到,在不同平台上看到的行为不同。我的是:sed --version This is not GNU sed version 4.0

于 2016-05-08T12:35:01.653 回答
7

另一种方法

awk 1 RS='\r\n' ORS=
  • 将记录分隔符设置为\r\n
  • 将输出记录分隔符设置为空字符串
  • 1总是正确的,并且在没有动作块的情况下{print}使用
于 2014-06-04T05:43:56.547 回答