以下脚本中的"\r"是什么作用?

35

我正在使用以下脚本通过 Telnet 重启我的路由器:

#!/usr/bin/env python

import os
import telnetlib
from time import sleep

host = "192.168.1.1"
user = "USER"
password = "PASSWORD"
cmd = "system restart"

tn = telnetlib.Telnet(host)
sleep(1)

tn.read_until("Login: ")
tn.write(user + "\n\r")
sleep(1)

tn.read_until("Password: ")
tn.write(password + "\n\r")
sleep(1)

tn.write(cmd + "\n\r")

我不知道为什么,但是移除 "\r" 就会破坏这段代码。那么在这个脚本中 "\r" 是用来做什么的?通常什么情况下需要使用 "\r"

注意:我知道“回车符”,但仍然无法弄清楚它在我的脚本中的用途。我正在 Linux 中运行此脚本。


2
这是一个回车符。 - sloth
我使用谷歌阅读了有关回车符的所有内容,但仍然无法弄清楚它在我的上述脚本中的用途。 - Alinwndrld
我建议你也看一下:http://docs.python.org/release/2.2.3/ref/strings.html,它解释了所有转义字符。 - Hugo
这个问题可能被问到是因为仅仅打印一个 \r 字符并不能使光标换行。 - octopusgrabbus
4个回答

42
'\r' 字符表示回车符,在网络虚拟终端会话中,换行需要使用回车符和换行符组合成的序列。

根据旧版Telnet规范(RFC 854)(第11页)的说明:

按照定义,“CR LF”序列将使NVT定位到下一行的左边界(例如,“LF CR”序列也是如此)。


然而,根据最新的规范(RFC5198)(第13页):
  1. ...

  2. 在Net-ASCII中,除非紧接着是NUL或LF,否则不得出现CR字符,后者(CR LF)表示“换行”函数。如上所述,今天和规定,CR通常只出现在LF之后。由于页面布局可用其他方式更好地完成,因为NUL在某些编程语言中具有特殊的解释,以及为避免其他类型的混淆,应优先避免CR NUL。

  3. 除非出现多个CR LF序列的副作用(例如,CR LF CR LF),否则不应出现LF CR。


因此,在Telnet中的换行应始终使用'\r\n',但大多数实现要么未更新,要么为了向后兼容性而保留旧的'\n\r'

是的,很棒,但请注意他使用 NL CR 而不是 CR NL... ;) - class stacker
@ClassStacker "\r\n" 是传统的版本,但反过来也可以。 - Some programmer dude
2
;) 只是想澄清一下:OP似乎不知道EOL的要求... - class stacker

24

'\r'表示回车,类似于'\n'表示换行或更常见的“新行”。

在打字机的旧时代,你必须将写字的滑轨移回到行的起始位置,并向下移动该行以便写入下一行。

在现代计算机时代,出于多种原因,我们仍然具有这种功能。但大多数情况下我们只使用'\n'并自动假设我们想从行的开头开始写,因为否则没有太多意义。

然而,有些情况下我们想仅使用'\r',如果我想要向输出写入内容,而不是进入新行并写入其他内容,这就是Linux或Windows命令行中许多程序可以具有“进度”信息且在同一行上更改的原因。

现在大多数系统仅使用'\n'表示换行。但某些系统同时使用两者。

你可以在其他答案中看到它们的用法示例。但最常见的是:

  • Windows使用'\r\n'结束行
  • Mac使用'\r'结束行
  • Unix / Linux使用'\n'

有些其他程序也有特定的用途。

有关这些字符历史的更多信息,请参阅维基百科


3
抱歉,但我不同意。这是TELNET协议本身需要\r\n作为行尾符号(在协议中定义的)。请参阅RFC854 - isedev
@isedev,我不确定你的评论与我的回答有什么关系。我认为你可能评论错了答案,或者请进一步解释一下。 - Inbar Rose
@Inbar:这只是指在这种情况下与操作系统无关。它是由TELNET协议规范定义的,与操作系统无关。 - isedev
@isedev,我说过它做了吗?你在批评我根本没有提到的观点? - Inbar Rose
2
@InbarRose 虽然有点偏题,但关于你的评论\r与\n相似。 我认为它们在(至少是Linux吧)上不同。 看看这个例子:print "bbb\raaaa" # 输出:aaaa print "__bbb\raaaa" # 输出:aaaab print "_____bbb\raaaa" # 输出:aaaa_bbb在这里,\r表示行结束并将光标移动到行首,并从那里打印后续字符。 - pravin
显示剩余3条评论

7

\r是ASCII码中的回车符(CR)字符。

不同的操作系统使用不同的换行约定。最常见的是:

  • CR+LF (\r\n);
  • LF (\n);
  • CR (\r)。

\n\r (LF+CR) 看起来很不寻常。

编辑:我对Telnet RFC的阅读表明:

  1. CR+LF是telnet协议使用的标准换行序列。
  2. LF+CR是可以接受的替代方案:

如定义的那样,序列“CR LF”将导致NVT定位在下一打印行的左边缘(例如,序列“LF CR”也会这样)。


1
抱歉,但我不同意。这是TELNET协议本身所要求的\r\n(在协议中定义为行尾序列)。请参见RFC854 - isedev
@isedev:我在RFC中看到了很多关于CR LF的提及,只有一次提及到了LF CR。你能指出具体的页面/章节吗? - NPE
作为一名诵读困难者,并不意味着通常的\r\n。我更确切的意思是,这与操作系统无关,而与TELNET协议本身有关(即在Linux上需要TELNET,在Windows上也需要TELNET)。 - isedev

0

实际上,这与通常的Windows / Unix \r\n vs \n问题没有任何关系。 TELNET协议本身将\r\n定义为行尾序列,与操作系统无关。请参见RFC854


2
不,TELNET将CR LF(即\r\n)定义为行尾序列。 - class stacker
2
每个人都开始教我回车符,但我已经知道了,并且开始在没有回答的情况下对我的问题进行投票。我认为你关于Telnet是正确的。 - Alinwndrld

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接