Lov*_*ths 1 linux sed newlines
我需要了解为什么 sed 能够为 1) 而不是 2) 工作。请不要向我发布任何替代解决方案。我已经在这个论坛上找到了它们。我只需要了解 sed 关于点 1) 和 2) 的行为。
1) sed -i s/\\r//g file.txt
在检查 od -c file.txt 时,sed 已成功删除 \r
2) sed -i s/\\n//g file.txt
在检查 od -c file.txt 时,sed 尚未删除 \n
我的问题是要了解为什么它不适用于第 2 点。请不要发布任何替代解决方案。希望了解内部结构就是这样!
sed 通过对每一行输入执行以下循环来操作:首先,sed 从输入流中读取一行,删除任何尾随的换行符,并将其放入模式空间。然后执行命令;每个命令都可以有一个与之关联的地址:地址是一种条件代码,只有在执行命令之前验证了条件时,才会执行命令。
当到达脚本末尾时,除非使用 -n 选项,否则模式空间的内容将打印到输出流中,如果删除了尾随换行符,则将其添加回。然后下一个循环开始下一个输入行。
来自POSIX 规范(感谢steeldriver提供链接)
在默认操作中, sed 应循环将一行输入(减去其终止换行符)附加到模式空间中。通常模式空间将是空的,除非 D 命令终止了最后一个循环。然后 sed 实用程序应按顺序应用其地址选择该模式空间的所有命令,并在脚本的末尾将模式空间复制到标准输出(指定 -n 时除外)并删除模式空间。每当模式空间被写入标准输出或命名文件时, sed 应立即在它后面加上一个换行符。
tl; dr在执行命令之前删除输入记录分隔符(默认情况下为换行符),然后在打印记录时添加回来
但是,在某些情况下可以操纵换行符。下面给出了一些例子:
$ # this would still not allow newline of second line to be manipulated
$ seq 5 | sed 'N; s/\n/ : /'
1 : 2
3 : 4
5
$ # here ASCII NUL is input record separator, so newline can be freely changed
$ seq 5 | sed -z 's/\n/ : /g'
1 : 2 : 3 : 4 : 5 :
$ # default newline separator, so NUL character can be changed
$ printf 'foo\0baz\0xyz\0' | sed 's/\x0/-/g'
foo-baz-xyz-
$ # NUL character is separator, so it cannot be changed now
$ printf 'foo\0baz\0xyz\0' | sed -z 's/\x0/-/g' | cat -A
foo^@baz^@xyz^@
Run Code Online (Sandbox Code Playgroud)