与script
模拟终端一样,它将换行字符 ( \n
) 转换为回车/换行序列 ( \r\n
)。OTOH,sed 将回车解释为一行的一部分,并在其后插入“$”。然后当它被输出到终端时,它通过将光标移动到行首并在那里继续输出来解释回车。
您可以通过管道输出到hexdump -C
. 首先比较cat
和script
输出:
$ cat test.txt | hexdump -C
00000000 66 69 72 73 74 20 6c 69 6e 65 0a 73 65 63 6f 6e |first line.secon|
00000010 64 20 6c 69 6e 65 0a 74 68 69 72 64 20 6c 69 6e |d line.third lin|
00000020 65 0a |e.|
00000022
$ script -c "cat test.txt" -q /dev/null | hexdump -C | cat
00000000 66 69 72 73 74 20 6c 69 6e 65 0d 0a 73 65 63 6f |first line..seco|
00000010 6e 64 20 6c 69 6e 65 0d 0a 74 68 69 72 64 20 6c |nd line..third l|
00000020 69 6e 65 0d 0a |ine..|
00000025
然后比较通过管道输出的输出sed
:
$ cat test.txt | sed -n 's/^\(.*\)$/\^\1\$/;p;' | hexdump -C
00000000 5e 66 69 72 73 74 20 6c 69 6e 65 24 0a 5e 73 65 |^first line$.^se|
00000010 63 6f 6e 64 20 6c 69 6e 65 24 0a 5e 74 68 69 72 |cond line$.^thir|
00000020 64 20 6c 69 6e 65 24 0a |d line$.|
00000028
$ script -c "cat test.txt" -q /dev/null | sed -n 's/^\(.*\)$/\^\1\$/;p;' | hexdump -C
00000000 5e 66 69 72 73 74 20 6c 69 6e 65 0d 24 0a 5e 73 |^first line.$.^s|
00000010 65 63 6f 6e 64 20 6c 69 6e 65 0d 24 0a 5e 74 68 |econd line.$.^th|
00000020 69 72 64 20 6c 69 6e 65 0d 24 0a |ird line.$.|
0000002b
因此,当script | sed
将其输出到终端时:
$first line
$^second line
$^third line
这就是发生的事情:
- 输出“^first line”,光标在行尾
- 输出“\r”,光标移动到行首(第0列)
- 输出“$”,覆盖“^”并将光标移动到第 1 列
- 输出“\n”,将光标移动到下一行,但将其留在第 1 列
- "^second line" 从第 1 列开始输出(此时第 0 列没有字符),光标在行尾
- 输出“\r”,将光标移动到行首(第 0 列)
- "$" 在第 0 列输出,将光标移动到第 1 列
- 输出“\n”,将光标移动到下一行,但将其留在第 1 列
- 等等
如果您仍想使用script
,请删除\r
字符。像这样:
script -c "cat test.txt" -q /dev/null | sed -n 's/\r//; s/^\(.*\)$/\^\1\$/;p;'
请注意,即使 sed 输出正常,您仍会在终端上看到“staircase”输出。我不确定为什么会发生这种情况,可能script
是修改终端设置。例如,如果通过“cat”管道输出,“楼梯”效果就会消失。