使用 STDIN.gets 时的多行输入问题
看过这个问题后,我有以下问题代码:
$/ = "\0"
answer = STDIN.gets
现在,我希望这将允许用户:
- 输入多行输入,通过按 Ctrl-D 终止。
- 输入单行输入,按 Ctrl-D 终止。
- 输入“无”输入,按 Ctrl-D 终止。
然而,我实际看到的行为是:
- 用户可以输入多行输入。
- 用户不能输入单行输入,除非他们按Ctrl-D两次。
- 如果用户立即按下 Ctrl-D,则可以输入“无”。
那么,为什么单行情况(即,如果用户输入了一些文本但没有换行符,然后点击 Ctrl-D)需要按两次 Ctrl-D 呢?如果用户什么都不输入,为什么它会起作用? (我注意到,如果他们什么都不输入并按 Ctrl-D,我不会得到空字符串,而是 nil 类 - 我在尝试调用 .empty 时发现了这一点? 结果,因为它突然失败了,如果有办法让它返回一个空字符串,那会很好,而不是检查
,并且并不特别想为 nil 类定义 .empty?
。 ==.empty?
。)
编辑:因为我真的很想知道“正确的为了在 Ruby 中做到这一点,我提供 200 个代表的赏金。我还将接受提供另一种通过合理的“提交”程序进入终端多行输入的方式的答案 - 我将成为“合适”的判断者。例如,我们当前使用两个“\n”,但这并不合适,因为它会阻塞段落并且不直观。
Having looked at this question, I have the following code:
$/ = "\0"
answer = STDIN.gets
Now, I was hoping that this would allow the user to:
- enter a multi-line input, terminating by pressing Ctrl-D.
- enter a single line input, terminating by pressing Ctrl-D.
- enter a "nothing" input, terminating by pressing Ctrl-D.
However, the behaviour I actually see is that:
- The user can enter a multi-line input fine.
- The user can not enter a single line input, unless they hit Ctrl-D twice.
- The user can enter a "nothing" input if they hit Ctrl-D straight away.
So, why does the single line situation (i.e. if the user has entered some text but no newline and then hit Ctrl-D) require two presses of Ctrl-D? And why does it work then if the user enters nothing? (I have noted that if they enter nothing and hit Ctrl-D, I don't get an empty string but the nil class - I discovered this when trying to call .empty?
on the result, since it suddenly failed horribly. If there is a way to get it to return an empty string as well, that would be nice. I prefer checking .empty?
to ==
, and don't particularly want to define .empty?
for the nil class.)
EDIT: Since I really would like to know the "correct way" to do this in Ruby, I am offering a bounty of 200 rep. I will also accept answers that give another way of entering terminal multi-line input with a sensible "submit" procedure - I will be the judge of 'suitable'. For example, we're currently using two "\n"s, but that's not suitable, as it blocks paragraphs and is unintuitive.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
基本问题是终端本身。请参阅帖子右侧的许多相关链接。为了解决这个问题,您需要将终端置于原始状态。以下内容在 Solaris 计算机上对我有用:
我不确定是否需要存储和恢复 stty 设置,但我见过其他人这样做。
The basic problem is the terminal itself. See many of the related links to the right of your post. To get around this you need to put the terminal in a raw state. The following worked for me on a Solaris machine:
I'm not sure if the storing and restoring of the stty settings is necessary but I've seen other people do it.
从终端设备读取 STDIN 时,您的工作模式与从文件或管道读取 STDIN 略有不同。
当从 tty 读取时,Control-D (EOF) 仅在输入缓冲区为空时才真正发送 EOF。如果它不为空,它将向读取系统调用返回数据,但不发送 EOF。
解决方案是使用一些较低级别的 IO 并一次读取一个字符。以下代码(或类似的代码)将执行您想要的操作
使用各种输入运行此代码的结果如下:-
INPUT 这是一行
INPUT 这是一行
输入
When reading STDIN from a terminal device you are working in a slightly different mode to reading STDIN from a file or a pipe.
When reading from a tty Control-D (EOF) only really sends EOF if the input buffer is empty. If it is not empty it returns data to the read system call but does not send EOF.
The solution is to use some lower level IO and read a character at a time. The following code (or somethings similar) will do what you want
The results of running this code with various inputs are as follows :-
INPUT This is a line<CR><Ctrl-D>
INPUT This is a line<Ctrl-D>
INPUT<Ctrl-D>