使用Mac OS X上的基本unix工具将行结尾转换为其他行结尾(sed,tr等)

时间:2013-08-20 19:55:20

标签: macos unix sed newline

特别是我正在尝试将所有\r\n转换为\r\r\n。这是因为iCloud的IMAP服务器发送\r\r\n打破协议和所有敏感性(我唯一的工作理论是他们这样做,所以他们只能在几年前发布时使用他们自己的IMAP客户端),我需要写单元测试来模拟这个。

在标准的unix工具中使用它非常棘手,因为它们处理行结尾的方式。

sed 's/\r\n/\r\r\n/g' - 不,不做任何事

sed 's/\r/\r\r/g' - 也什么都不做

tr在处理字符串方面没有太大作用;它只对单个字符进行操作,并且似乎保留了#个字符。

我真的不确定如何使用Unix工具来做这么低级别的事情。最糟糕的情况我可以在C的几行中做到这一点,但我想学习如何更标准地做到这一点。

根据Jim的回答,Mac OS X(BSD)上的sed版本似乎与Linux有所不同。理想情况下,我需要Mac解决方案,尽管我可以或多或少地在不同的机器上完成这项工作。

4 个答案:

答案 0 :(得分:2)

如果您使用bash作为shell,则可以使用其ANSI C quoting功能强制Mac OS X sed按需运行。

sed -e $'s/$/\r\r/'

$'...'是ANSI C引用的字符串。大多数(只是)内部角色没有改变;两个\r序列将被字符串中的回车替换。

例如:

$ sed -e $'s/$/\r\r/' genouterr.sh | odx
0x0000: 23 21 2F 62 69 6E 2F 62 61 73 68 0D 0D 0A 66 6F   #!/bin/bash...fo
0x0010: 72 20 69 20 69 6E 20 7B 30 31 2E 2E 35 30 7D 0D   r i in {01..50}.
0x0020: 0D 0A 64 6F 0D 0D 0A 20 20 65 63 68 6F 20 22 73   ..do...  echo "s
0x0030: 74 64 6F 75 74 20 24 69 22 0D 0D 0A 20 20 65 63   tdout $i"...  ec
0x0040: 68 6F 20 22 73 74 64 65 72 72 20 24 69 22 20 3E   ho "stderr $i" >
0x0050: 26 32 0D 0D 0A 64 6F 6E 65 0D 0D 0A               &2...done...
0x005C:
$

十六进制转储(odx是一个家庭酿造程序,但我喜欢它的格式)显示每个换行符(0A)之前有两个\r(0D)字节,而不是原版的。显然,十六进制转储程序的选择不会影响sed命令和ANSI C引用机制的有效性。

如果您需要将CRLF更改为CRCRLF,那么您可以使用:

sed -e $'s/\r$/\r\r/'

如果你想删除回车符,但只是在一行的末尾,那么你可以使用:

sed -e $'s/\r\r*$//'

tr可用于删除所有回车符,但不仅可用于换行符之前的回车符。)

答案 1 :(得分:1)

您可以使用行尾锚点字符'$'来完成您想要的任务:

% od -c foo
0000000   l   i   n   e   1  \r  \n   l   i   n   e   2  \r  \n   l   i
0000020   n   e   3  \r  \n
0000025
% sed 's/\r$/\r\r/g' < foo > bar
% od -c bar
0000000   l   i   n   e   1  \r  \r  \n   l   i   n   e   2  \r  \r  \n
0000020   l   i   n   e   3  \r  \r  \n
0000030

上面的内容适用于GNU sed,但不适用于BSD sed(不处理\ r \ n 正如人们所期望的那样在替换字符串中)。在Mac或其他BSD-ish sed变体上,您应该能够完成 通过指定反斜杠转义的文字(空白)ASCII返回来进行所需的替换 字符。

有关详细信息,请参阅this question

答案 2 :(得分:1)

MacOSX上的'sed'与linux上的行为略有不同。您可能需要尝试this source的说明。

sed -e 's/ /\'$'\n/g'

添加了一个新行。

还有另一个选项可以使用'gsed',这是一个更现代的sed版本(与linux相比)。那里你可以使用linux解决方案:sed's / \ r \ n / \ r \ r \ n \ n / g'

答案 3 :(得分:1)

在OSX上执行此操作的一种方法是使用awk

awk '/\r$/ {printf "%s\r\n", $0}' file

如果您想要仅限sed ,那么这应该适用于OSX:

sed -i.bak "s/"$'\r'"$/&&/" file