为什么';t sed';s/\r\n/\r/g';按预期工作?

为什么';t sed';s/\r\n/\r/g';按预期工作?,sed,line-endings,Sed,Line Endings,在正常的windows到unix转换中,您可以执行类似于sed s/\r//g的操作,从流中删除\r字符 但我正在尝试转换可以是mac编码(\r)或windows编码(\r\n)的文件的结束行。因此,我不能只删除\r,因为它会删除mac结尾(如果有)。我必须先“规范化”行尾字符。此规范化步骤将\r\n转换为\r(之后我将执行\r\n转换)。然而,我无法用sed解决这个步骤。我试过这样的方法: $> echo -e "foo\r\nbar" | sed 's/\r\n/\r/g' | xxd

在正常的windows到unix转换中,您可以执行类似于
sed s/\r//g
的操作,从流中删除\r字符

但我正在尝试转换可以是mac编码(\r)或windows编码(\r\n)的文件的结束行。因此,我不能只删除\r,因为它会删除mac结尾(如果有)。我必须先“规范化”行尾字符。此规范化步骤将\r\n转换为\r(之后我将执行\r\n转换)。然而,我无法用
sed
解决这个步骤。我试过这样的方法:

$> echo -e "foo\r\nbar" | sed 's/\r\n/\r/g' | xxd -c 24 -g 1
00000000: 66 6f 6f 0d 0a 62 61 72 0a            foo..bar.
$> echo -e "foo\r\nbar" | bbe -e 's/\r\n/\r/g' | xxd -c 24 -g 1
00000000: 66 6f 6f 0d 62 61 72 0a               foo.bar.
我用bbe解决了这个问题,如下所示:

$> echo -e "foo\r\nbar" | sed 's/\r\n/\r/g' | xxd -c 24 -g 1
00000000: 66 6f 6f 0d 0a 62 61 72 0a            foo..bar.
$> echo -e "foo\r\nbar" | bbe -e 's/\r\n/\r/g' | xxd -c 24 -g 1
00000000: 66 6f 6f 0d 62 61 72 0a               foo.bar.

sed是否也可以这样做?

sed
默认情况下会分割
\n
上的输入,因此
\n
永远不会在模式空间中结束。但是,如果您使用的是GNU
sed
,则可以使用选项使
sed
将输入视为
NUL
字符分隔行:

$ echo -e "foo\r\nbar" | sed -z 's/\r\n/\r/g' | hd
00000000  66 6f 6f 0d 62 61 72 0a                           |foo.bar.|
或者,在POSIX
sed
中,您可以将所有行附加到模式空间(在循环中),有效地将完整文件复制到模式空间,然后执行替换:

$ echo -e "foo\r\nbar" | sed -n ':a;N;ta; s/\r\n/\r/g; p' | hd
00000000  66 6f 6f 0d 62 61 72 0a                           |foo.bar.|

您可以使用
perl
,它不像sed/awk那样删除记录分隔符。此解决方案不需要对整个文件进行SLURP

$ echo -e 'foo\r\nbar' | perl -pe 's/\r\n/\r/' | xxd -c 24 -g 1
00000000: 66 6f 6f 0d 62 61 72 0a                foo.bar.
请注意,
g
修饰符不需要,因为每个记录只能出现一次
\n