1

特别是我试图将所有转换\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

4 回答 4

3

如果您将bash其用作 shell,则可以使用其ANSI C 引用功能来强制 Mac OS Xsed按您的需要工作。

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是一个自制程序,但我喜欢它的格式)显示\r每个换行符(0A)之前有两个(0D)字节,而原始字节中没有。显然,十六进制转储程序的选择不影响sed命令的有效性和 ANSI C 引用机制。

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

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

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

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

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

于 2013-08-20T20:35:59.480 回答
2

MacOSX 上的“sed”与 linux 上的行为略有不同。您可能想尝试此来源的说明。

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

这增加了一个新行。

还有另一种使用“gsed”的选项,它是更现代的 sed 版本(类似于 linux)。在那里您可能可以使用 linux 解决方案: sed 's/\r\n/\r\r\n/g'

于 2013-08-20T20:28:18.317 回答
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 视为替换字符串中所期望的那样)。在 Mac 或其他 BSD-ish sed 变体上,您应该能够通过指定反斜杠转义文字(空白)ASCII 返回字符来完成所需的替换。

有关详细信息,请参阅此问题

于 2013-08-20T20:01:58.863 回答
1

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

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

如果你只想要 sed那么这应该在 OSX 上工作:

sed -i.bak "s/"$'\r'"$/&&/" file
于 2013-08-20T20:41:11.303 回答