使用sed将CR转换为LF

时间:2017-03-20 21:51:04

标签: windows sed

我在Windows上有一个包含CR和CRLF的文件。

我在上面运行了这个命令:

$ sed -i 's \x0d \x0a ' foo

我得到的是:

  1. 未跟随LF的所有CR都转换为LF
  2. 但是

    1. 属于CRLF的那些CR保持不变。
    2. 为什么会这样?

2 个答案:

答案 0 :(得分:2)

假设您在 Unix 平台上运行此操作,使用 GNU sed

sed -i 's/\r/\n/g; s/\n$//' foo

这将替换所有已隔离的CR(\r\x0d)实例以及 one LF的CRLF(\r\n\x0d\x0a)序列(\n\x0a)每个 - 请参阅底部以获得解释。

至于您尝试的内容(同样,假设您在 Unix 平台上运行此操作,使用 GNU {{1} }):

  • sed读取所有内容,但不包括LF(sed)作为单行,并且在输出上,终止该行LF。

  • 在您的情况下,这意味着单行读取将结束在CR(\n)中(由于\r读取到CRLF,剥离LF ),可能在该行中包含隔离的 CR实例。

  • sed,由于未使用选项's \x0d \x0a ',因此将最多1个 CR字符替换为

应该导致:

  • 每行的第一个 CR(g\r)实例应该已替换为LF(\x0d,{{1} })

  • 当前行上的任何其他CR实例 - 包括一个属于行结束CRLF序列的CR实例 - 都将一个接一个。

为什么正确的解决方案需要两个 \n来电?

  • \x0a 全局s)使用LF替换当前行中的所有 CR('s/\r/\n/g')实例g

  • 因为作为行结束CRLF一部分的CR也被\r替换,所以内容行(模式空间,在{{1}中现在\n 结束。

  • 因为\n总是在输出上追加一个LF(sed),所以必须删除额外的尾随\n,这就是{{ 1}}确实。

答案 1 :(得分:1)

此行为的原因是unix中以\r结尾的行显示为一行,下一行包含\n

$ echo -e "line1\rline2\r\nline3" |cat -A
line1^Mline2^M$
line3$

结果你的sed,没有g选项,将取代这个“连接”行中的第一个\ r \ n:

$ echo -e "line1\rline2\r\nline3" |sed 's \x0d \x0a ' |cat -A
line1$
line2^M$ #this is same input line as line1 and thus \r is not replaced the second time in the same line without g
line3$

如果在同一个被认为是输入行的内容中多次找到\r,则需要包含g以进行全局替换:

$ echo -e "line1\rline2\r\nline3\rline4\r\nline5\r\nline6" |cat -A
line1^Mline2^M$   #line2 \r will not be replaced without g
line3^Mline4^M$   #line4 \r will not be replaced without g
line5^M$          # This \r will be replaced since it is unique on input line 
line6$

$ echo -e "line1\rline2\r\nline3\rline4\r\nline5\r\nline6" |sed 's \r \n ' |cat -A
line1$
line2^M$
line3$
line4^M$
line5$  #the \r is removed from here even without g , since input line5 was alone
$
line6$

$ echo -e "line1\rline2\r\nline3\rline4\r\nline5\r\nline6" |sed 's \r \n g' |cat -A
line1$
line2$
$
line3$
line4$
$
line5$
$
line6$

注意:
从上述测试中可以明显看出,将\r替换为\n会使CRLF成为LFLF = \n\n,这会产生额外的空白行。这可能是也可能不是所希望的。这个额外的行可以按照建议删除,即回答mklement0